Feat: Enhance query intent search and answer format readability
This commit is contained in:
@@ -21,7 +21,7 @@ export function buildProjectChronicleGuardContext(project: ProjectProfile | null
|
||||
'',
|
||||
'Required response order for new ideas or feature requests:',
|
||||
'1. Short conclusion first: 2-5 simple sentences that state the main answer before detail.',
|
||||
'2. Brief summary: 3-5 bullets or a compact paragraph that previews the full answer.',
|
||||
'2. Brief summary: one compact paragraph by default. Avoid bullet-heavy formatting.',
|
||||
'3. Detailed answer.',
|
||||
'4. Request summary.',
|
||||
'5. Inferred user intent.',
|
||||
@@ -46,10 +46,15 @@ export function buildProjectChronicleGuardContext(project: ProjectProfile | null
|
||||
'- If only general/reference notes are available, avoid phrases like "the current architecture has..." or "the project is prepared for..." and use "if implemented" or "needs verification" wording.',
|
||||
'- If only general/reference notes are available, explicitly say: "현재 정보만으로는 기술 구조를 판단할 수 없습니다."',
|
||||
'- Without project evidence, never say the architecture is flexible, technically stable, scalable, gateway-based, microservice-ready, layered, or structurally prepared.',
|
||||
'- When the user asks about customer evaluation, approval likelihood, development direction fit, business value, UX, customer journey, product discovery, or purchase conversion, treat the answer as a UX/business inference unless explicit approval criteria are provided.',
|
||||
'- For approval/evaluation questions, prefer this structure: confirmed facts, inference, general UX/business principle, needs verification, recommended direction.',
|
||||
'- Be realistic about approval: if the user has not shown that the experience connects to product discovery or purchase conversion, say that revision or clarification requests are likely rather than saying it may be positive.',
|
||||
'',
|
||||
'Tone and scope:',
|
||||
'- Be practical and plain-spoken.',
|
||||
'- Keep the top conclusion calm and short so the user can understand the answer before reading the long version.',
|
||||
'- Prefer short paragraphs with blank lines between numbered sections. Avoid starting most lines with `*` or `-` bullets.',
|
||||
'- Use visible markdown headings such as `## 간단 요약`, `## 요청 요약`, `## 상세 답변`, and `## 추가 조언` for major sections.',
|
||||
'- Avoid grand phrases like advanced cognitive architecture, compounding knowledge, perfect graph, or ultimate knowledge distiller.',
|
||||
'- When the user wants low dependency, keep the first proposal to Markdown, JSON, local files, and explicit user save actions.',
|
||||
'- Do not jump directly to large architectures. Narrow direction before expanding.',
|
||||
|
||||
@@ -3,6 +3,7 @@ import * as path from 'path';
|
||||
import { findBrainFiles, summarizeText } from '../utils';
|
||||
|
||||
export type SecondBrainSourceType = 'Project Evidence' | 'User Decision' | 'General Knowledge' | 'Reference Only';
|
||||
export type SecondBrainQueryIntent = 'technical' | 'ux-business' | 'governance' | 'general';
|
||||
|
||||
export interface SecondBrainTraceDocument {
|
||||
title: string;
|
||||
@@ -21,6 +22,7 @@ export interface SecondBrainTraceDocument {
|
||||
|
||||
export interface SecondBrainTrace {
|
||||
userQuery: string;
|
||||
queryIntent: SecondBrainQueryIntent;
|
||||
shouldUseSecondBrain: boolean;
|
||||
secondBrainUsed: boolean;
|
||||
reason: string;
|
||||
@@ -38,9 +40,11 @@ export function buildSecondBrainTrace(userQuery: string, brainRoot: string, opti
|
||||
} = {}): SecondBrainTrace {
|
||||
const query = userQuery.trim();
|
||||
const shouldUseSecondBrain = !!options.force || shouldUseBrain(query);
|
||||
const retrievalQuery = buildRetrievalQuery(query);
|
||||
const queryIntent = classifyQueryIntent(query);
|
||||
const retrievalQuery = buildRetrievalQuery(query, queryIntent);
|
||||
const baseTrace: SecondBrainTrace = {
|
||||
userQuery: query,
|
||||
queryIntent,
|
||||
shouldUseSecondBrain,
|
||||
secondBrainUsed: false,
|
||||
reason: shouldUseSecondBrain
|
||||
@@ -66,7 +70,7 @@ export function buildSecondBrainTrace(userQuery: string, brainRoot: string, opti
|
||||
const files = findBrainFiles(brainRoot)
|
||||
.filter((file) => includeRaw || !isRawConversationPath(path.relative(brainRoot, file)));
|
||||
const terms = tokenize(retrievalQuery);
|
||||
const scored = files.map((file) => scoreFile(file, brainRoot, terms))
|
||||
const scored = files.map((file) => scoreFile(file, brainRoot, terms, queryIntent))
|
||||
.filter((doc) => doc.score >= 0.25)
|
||||
.sort((a, b) => b.score - a.score)
|
||||
.slice(0, options.limit || 5);
|
||||
@@ -134,6 +138,7 @@ export function renderSecondBrainTraceContext(trace: SecondBrainTrace): string {
|
||||
return [
|
||||
'[SECOND BRAIN TRACE]',
|
||||
`Second Brain used: ${trace.secondBrainUsed ? 'yes' : 'no'}`,
|
||||
`Query intent: ${trace.queryIntent}`,
|
||||
`Retrieval query: ${trace.retrievalQuery}`,
|
||||
`Reason: ${trace.reason}`,
|
||||
docs ? `Selected notes:\n${docs}` : 'Selected notes: none',
|
||||
@@ -143,6 +148,12 @@ export function renderSecondBrainTraceContext(trace: SecondBrainTrace): string {
|
||||
'No Evidence, No Project Claim: do not state that the current project has a technical structure unless it is supported by user-provided facts, source code, design docs, project docs, or project records.',
|
||||
'General Knowledge notes can explain concepts, but cannot prove the current project actually implements those concepts.',
|
||||
'Classify major claims as Confirmed, Inference, General Knowledge, or Needs Verification when the answer discusses a project.',
|
||||
trace.queryIntent === 'ux-business'
|
||||
? 'This is a UX/business/approval-fit question. Prefer customer journey, product discovery, requirement fit, business value, stakeholder approval, acceptance criteria, and conversion-flow reasoning over technical architecture reasoning.'
|
||||
: '',
|
||||
trace.queryIntent === 'ux-business'
|
||||
? 'Approval likelihood is an inference unless explicit approval criteria are provided. Use wording such as "보완 요청 가능성이 높습니다", "승인 가능성을 높일 수 있습니다", and "확인 필요".'
|
||||
: '',
|
||||
hasProjectEvidence
|
||||
? 'At least one selected note can support project-specific claims.'
|
||||
: 'No selected note can support project-specific implementation claims.',
|
||||
@@ -189,6 +200,9 @@ export function renderSecondBrainTraceMarkdown(trace: SecondBrainTrace, debug: b
|
||||
'## 2nd Brain 사용 여부',
|
||||
status,
|
||||
'',
|
||||
'## 질문 의도',
|
||||
trace.queryIntent,
|
||||
'',
|
||||
'## 이유',
|
||||
trace.reason,
|
||||
'',
|
||||
@@ -214,6 +228,7 @@ export function renderSecondBrainTraceMarkdown(trace: SecondBrainTrace, debug: b
|
||||
JSON.stringify({
|
||||
secondBrainUsed: trace.secondBrainUsed,
|
||||
shouldUseSecondBrain: trace.shouldUseSecondBrain,
|
||||
queryIntent: trace.queryIntent,
|
||||
retrievalQuery: trace.retrievalQuery,
|
||||
searchedCollections: trace.searchedCollections,
|
||||
retrievedDocuments: trace.retrievedDocuments.map((doc) => ({
|
||||
@@ -311,11 +326,35 @@ function deriveProjectClaimPolicy(
|
||||
|
||||
function shouldUseBrain(query: string): boolean {
|
||||
const normalized = query.toLowerCase();
|
||||
return /(second brain|2nd brain|제2뇌|브레인|brain|기억|기록|문서|노트|내가|우리|프로젝트|결정|adr|chronicle|가드|설계 원칙|mvp|제외|왜|dependency|schema|documentation|drift|integration|overhead|의존성|스키마|문서화)/i.test(normalized);
|
||||
return /(second brain|2nd brain|제2뇌|브레인|brain|기억|기록|문서|노트|내가|우리|프로젝트|결정|adr|chronicle|가드|설계 원칙|mvp|제외|왜|dependency|schema|documentation|drift|integration|overhead|의존성|스키마|문서화|고객|사용자|ux|경험|구매|전환|상품|공간|요구사항|승인|평가|비즈니스|가치|stakeholder|approval|customer|journey|conversion|requirement)/i.test(normalized);
|
||||
}
|
||||
|
||||
function buildRetrievalQuery(query: string): string {
|
||||
return tokenize(query).slice(0, 16).join(' ');
|
||||
function classifyQueryIntent(query: string): SecondBrainQueryIntent {
|
||||
const normalized = query.toLowerCase();
|
||||
if (/(고객|사용자|ux|경험|구매|전환|상품|공간|요구사항|승인|평가|비즈니스|가치|웹스토어|virtual store|stakeholder|approval|customer|journey|conversion|requirement|acceptance|product discovery|business value)/i.test(normalized)) {
|
||||
return 'ux-business';
|
||||
}
|
||||
if (/(dependency|schema|documentation|drift|integration|overhead|의존성|스키마|문서화|보안|검증|리스크|governance|reliability)/i.test(normalized)) {
|
||||
return 'governance';
|
||||
}
|
||||
if (/(api|gateway|architecture|microservice|monolith|database|backend|frontend|routing|아키텍처|기술|라우팅|데이터|서버|클라이언트)/i.test(normalized)) {
|
||||
return 'technical';
|
||||
}
|
||||
return 'general';
|
||||
}
|
||||
|
||||
function buildRetrievalQuery(query: string, intent: SecondBrainQueryIntent): string {
|
||||
const intentTerms: Record<SecondBrainQueryIntent, string[]> = {
|
||||
'ux-business': [
|
||||
'ux', 'customer journey', 'product discovery', 'virtual store', 'stakeholder approval',
|
||||
'requirement fit', 'business value proposition', 'acceptance criteria', 'conversion flow',
|
||||
'고객 경험', '상품 탐색', '구매 전환', '요구사항 적합성', '승인 기준', '비즈니스 가치'
|
||||
],
|
||||
technical: ['architecture', 'routing', 'api', 'implementation', 'source code', 'design document'],
|
||||
governance: ['dependency', 'schema drift', 'documentation', 'validation', 'risk', 'decision'],
|
||||
general: []
|
||||
};
|
||||
return [...tokenize(query), ...intentTerms[intent]].slice(0, 28).join(' ');
|
||||
}
|
||||
|
||||
function tokenize(value: string): string[] {
|
||||
@@ -331,7 +370,7 @@ function tokenize(value: string): string[] {
|
||||
.filter((term) => term.length >= 2 && !stopWords.has(term));
|
||||
}
|
||||
|
||||
function scoreFile(file: string, brainRoot: string, terms: string[]): SecondBrainTraceDocument {
|
||||
function scoreFile(file: string, brainRoot: string, terms: string[], intent: SecondBrainQueryIntent): SecondBrainTraceDocument {
|
||||
const relative = path.relative(brainRoot, file);
|
||||
const title = path.basename(file, path.extname(file));
|
||||
const basename = relative.toLowerCase();
|
||||
@@ -345,7 +384,7 @@ function scoreFile(file: string, brainRoot: string, terms: string[]): SecondBrai
|
||||
const canSupportProjectClaim = sourceType === 'Project Evidence' || sourceType === 'User Decision';
|
||||
|
||||
const lower = content.toLowerCase();
|
||||
let score = pathPriority(relative);
|
||||
let score = pathPriority(relative, intent);
|
||||
for (const term of terms) {
|
||||
if (basename.includes(term)) score += 4;
|
||||
const matches = lower.split(term).length - 1;
|
||||
@@ -388,7 +427,7 @@ function isRawConversationPath(relativePath: string): boolean {
|
||||
return /(^|[\\/])(00_Raw|raw-data|conversations?|transcripts?)([\\/]|$)/i.test(relativePath);
|
||||
}
|
||||
|
||||
function pathPriority(relativePath: string): number {
|
||||
function pathPriority(relativePath: string, intent: SecondBrainQueryIntent): number {
|
||||
const normalized = relativePath.toLowerCase();
|
||||
let score = 0;
|
||||
if (/(^|[\\/])(decisions?|adr|planning|development|bugs|retrospectives|records)([\\/]|$)/i.test(normalized)) {
|
||||
@@ -403,6 +442,17 @@ function pathPriority(relativePath: string): number {
|
||||
if (/(^|[\\/])index(_\d+)?\.md$/i.test(normalized) || /[\\/]index\.md$/i.test(normalized)) {
|
||||
score -= 2;
|
||||
}
|
||||
if (intent === 'ux-business') {
|
||||
if (/(ux|customer|journey|product|discovery|virtual|store|stakeholder|approval|requirement|business|value|acceptance|conversion|commerce|webstore|고객|사용자|경험|상품|구매|전환|공간|요구사항|승인|평가|비즈니스|가치)/i.test(normalized)) {
|
||||
score += 5;
|
||||
}
|
||||
if (/(api|gateway|microservice|monolithic|backend|database|routing|architecture_principles|programming)/i.test(normalized)) {
|
||||
score -= 3;
|
||||
}
|
||||
}
|
||||
if (intent === 'technical' && /(api|gateway|microservice|architecture|routing|backend|database)/i.test(normalized)) {
|
||||
score += 2;
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
@@ -1992,7 +1992,12 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
}
|
||||
|
||||
.markdown-body h1 { font-size: 1.5em; border-bottom: 1px solid var(--border); padding-bottom: 0.3em; color: var(--accent); }
|
||||
.markdown-body h2 { font-size: 1.3em; border-bottom: 1px solid var(--border); padding-bottom: 0.3em; }
|
||||
.markdown-body h2 { font-size: 1.45em; border-bottom: 1px solid var(--border); padding-bottom: 0.3em; }
|
||||
.markdown-body h3 { font-size: 1.2em; }
|
||||
.markdown-body p { margin: 0.75em 0 1.1em; }
|
||||
.markdown-body ol, .markdown-body ul { margin: 0.7em 0 1.1em; padding-left: 1.45em; }
|
||||
.markdown-body li { margin: 0.35em 0 0.65em; }
|
||||
.markdown-body li + li { margin-top: 0.55em; }
|
||||
.markdown-body table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
+5
-2
@@ -150,8 +150,10 @@ Core behavior:
|
||||
- Do not output hidden reasoning labels such as [PROBLEM], [GOAL], [REASONING], Phase 0, Fidelity Lock-in, or process manifestos.
|
||||
- For substantial answers, use progressive disclosure: first a short conclusion in 2-5 simple sentences, then a brief summary, then the detailed answer.
|
||||
- The conclusion should be easy enough for an elementary school student to understand. Put the main point before nuance.
|
||||
- Keep the brief summary compact: 3-5 bullets or a short paragraph.
|
||||
- Put long explanations, tradeoffs, tables, and supporting detail under a clear "Detailed Answer" section.
|
||||
- Prefer paragraph-style formatting over bullet-heavy formatting. Do not put asterisks or dash bullets at the start of most lines.
|
||||
- Keep the brief summary compact as 1 short paragraph by default. Use a numbered list only when sequence matters, and keep a blank line between numbered sections.
|
||||
- Use visible markdown headings such as "## 간단 요약", "## 요청 요약", and "## 상세 답변" for major sections so the UI can render them larger.
|
||||
- Put long explanations, tradeoffs, tables, and supporting detail under a clear "## 상세 답변" section.
|
||||
- Avoid wall-of-text output. Make the answer understandable before adding detail.
|
||||
- Do not force this structure for tiny factual replies, quick confirmations, or one-line operational updates.
|
||||
- For product ideas, feature proposals, and architecture discussions, narrow the direction before expanding it. Prefer a practical MVP first, then separate later expansion ideas.
|
||||
@@ -161,6 +163,7 @@ Core behavior:
|
||||
- Even if Second Brain provides a general concept note, do not describe that concept as actually implemented in the current project. General concept notes are not project evidence.
|
||||
- For project opinions, separate claims into confirmed facts, inferences, general knowledge, and items that need verification.
|
||||
- If available evidence is only general knowledge, never say the project architecture is flexible, technically stable, scalable, gateway-based, microservice-ready, separated into layers, or structurally prepared. Say the technical structure cannot be judged from the current information.
|
||||
- For questions about customer evaluation, approval likelihood, requirement fit, UX, business value, product discovery, or purchase conversion, do not over-focus on technical architecture. Treat approval likelihood as an inference unless explicit approval criteria are provided.
|
||||
|
||||
Available action tags:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user