Feat: Enhance query intent search and answer format readability
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
# Development Log: Answer Format Readability Tuning
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Reduce visual clutter in assistant answers by discouraging bullet-heavy output and improving markdown heading readability in the chat UI.
|
||||||
|
|
||||||
|
## User Feedback
|
||||||
|
The answer content was useful, but many lines started with bullet dots, making the whole response feel visually messy. The user also wanted major sections such as simple summary, request summary, and additional advice to stand out more clearly.
|
||||||
|
|
||||||
|
## Implementation Summary
|
||||||
|
- Updated the base system prompt to prefer short paragraphs over bullet-heavy formatting.
|
||||||
|
- Changed brief summary guidance from bullets to a compact paragraph by default.
|
||||||
|
- Added guidance to separate numbered sections with blank lines.
|
||||||
|
- Added guidance to use visible markdown headings such as `## 간단 요약`, `## 요청 요약`, and `## 상세 답변`.
|
||||||
|
- Updated Project Chronicle Guard prompt with the same paragraph-first and heading guidance.
|
||||||
|
- Increased markdown heading visibility in the sidebar UI.
|
||||||
|
- Added paragraph and list spacing styles so markdown output is less cramped.
|
||||||
|
|
||||||
|
## Changed Files
|
||||||
|
- `src/utils.ts`
|
||||||
|
- `src/features/projectChronicle/guardPrompt.ts`
|
||||||
|
- `src/sidebarProvider.ts`
|
||||||
|
- `tests/projectChronicleGuardPrompt.test.ts`
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
- `./node_modules/.bin/tsc --noEmit`
|
||||||
|
- `npm run compile`
|
||||||
|
- `./node_modules/.bin/jest --runInBand`
|
||||||
|
|
||||||
|
## Result
|
||||||
|
Future answers should start with a short conclusion, use fewer bullet dots, separate numbered sections more clearly, and show major headings with better visual hierarchy.
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Development Log: Query Intent Search Tuning
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Improve Second Brain search relevance and answer framing for questions about customer evaluation, approval likelihood, UX, business value, and requirement fit.
|
||||||
|
|
||||||
|
## User Feedback
|
||||||
|
The answer became safer, but Second Brain still retrieved architecture documents for a question that was really about customer experience, approval risk, and business direction. Approval likelihood should also be labeled as inference, not fact.
|
||||||
|
|
||||||
|
## Implementation Summary
|
||||||
|
- Added `queryIntent` classification to Second Brain Trace:
|
||||||
|
- `technical`
|
||||||
|
- `ux-business`
|
||||||
|
- `governance`
|
||||||
|
- `general`
|
||||||
|
- Expanded retrieval query terms based on intent.
|
||||||
|
- For `ux-business`, boosted UX, customer journey, product discovery, virtual store, stakeholder approval, requirement fit, business value, acceptance criteria, and conversion-flow documents.
|
||||||
|
- For `ux-business`, penalized API Gateway, microservice, monolithic, backend, database, routing, and generic architecture-principles paths.
|
||||||
|
- Added Trace context guidance that approval likelihood is inference unless explicit approval criteria are provided.
|
||||||
|
- Added base and Guard prompt guidance to prefer UX/business framing over technical architecture for these questions.
|
||||||
|
- Added tests to verify UX/business docs outrank API Gateway docs for approval/customer-experience questions.
|
||||||
|
|
||||||
|
## Changed Files
|
||||||
|
- `src/features/secondBrainTrace.ts`
|
||||||
|
- `src/features/projectChronicle/guardPrompt.ts`
|
||||||
|
- `src/utils.ts`
|
||||||
|
- `tests/secondBrainTrace.test.ts`
|
||||||
|
- `tests/projectChronicleGuardPrompt.test.ts`
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
- `./node_modules/.bin/tsc --noEmit`
|
||||||
|
- `npm run compile`
|
||||||
|
- `./node_modules/.bin/jest --runInBand`
|
||||||
|
|
||||||
|
## Result
|
||||||
|
Second Brain Trace should now better match the user's question intent. Customer approval and UX/business-fit questions should retrieve customer journey and business-value notes before generic technical architecture notes.
|
||||||
@@ -18,3 +18,5 @@
|
|||||||
- Added No Evidence, No Project Claim rules and Second Brain source type classification to prevent general notes from being treated as project implementation evidence.
|
- Added No Evidence, No Project Claim rules and Second Brain source type classification to prevent general notes from being treated as project implementation evidence.
|
||||||
- Added project claim policy enforcement so main answers must treat general-only or mixed evidence as cautious and avoid unsupported technical structure claims.
|
- Added project claim policy enforcement so main answers must treat general-only or mixed evidence as cautious and avoid unsupported technical structure claims.
|
||||||
- Added a deterministic output brake that removes unsupported technical structure claims from final answers when Trace policy is `general-only`.
|
- Added a deterministic output brake that removes unsupported technical structure claims from final answers when Trace policy is `general-only`.
|
||||||
|
- Tuned Second Brain retrieval by query intent so UX/business/approval questions prioritize customer journey, requirement fit, and business value notes over generic architecture notes.
|
||||||
|
- Tuned answer readability: paragraph-first summaries, fewer bullet-heavy sections, clearer numbered-section spacing, and larger markdown headings in the sidebar.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function buildProjectChronicleGuardContext(project: ProjectProfile | null
|
|||||||
'',
|
'',
|
||||||
'Required response order for new ideas or feature requests:',
|
'Required response order for new ideas or feature requests:',
|
||||||
'1. Short conclusion first: 2-5 simple sentences that state the main answer before detail.',
|
'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.',
|
'3. Detailed answer.',
|
||||||
'4. Request summary.',
|
'4. Request summary.',
|
||||||
'5. Inferred user intent.',
|
'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, 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: "현재 정보만으로는 기술 구조를 판단할 수 없습니다."',
|
'- 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.',
|
'- 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:',
|
'Tone and scope:',
|
||||||
'- Be practical and plain-spoken.',
|
'- Be practical and plain-spoken.',
|
||||||
'- Keep the top conclusion calm and short so the user can understand the answer before reading the long version.',
|
'- 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.',
|
'- 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.',
|
'- 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.',
|
'- 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';
|
import { findBrainFiles, summarizeText } from '../utils';
|
||||||
|
|
||||||
export type SecondBrainSourceType = 'Project Evidence' | 'User Decision' | 'General Knowledge' | 'Reference Only';
|
export type SecondBrainSourceType = 'Project Evidence' | 'User Decision' | 'General Knowledge' | 'Reference Only';
|
||||||
|
export type SecondBrainQueryIntent = 'technical' | 'ux-business' | 'governance' | 'general';
|
||||||
|
|
||||||
export interface SecondBrainTraceDocument {
|
export interface SecondBrainTraceDocument {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -21,6 +22,7 @@ export interface SecondBrainTraceDocument {
|
|||||||
|
|
||||||
export interface SecondBrainTrace {
|
export interface SecondBrainTrace {
|
||||||
userQuery: string;
|
userQuery: string;
|
||||||
|
queryIntent: SecondBrainQueryIntent;
|
||||||
shouldUseSecondBrain: boolean;
|
shouldUseSecondBrain: boolean;
|
||||||
secondBrainUsed: boolean;
|
secondBrainUsed: boolean;
|
||||||
reason: string;
|
reason: string;
|
||||||
@@ -38,9 +40,11 @@ export function buildSecondBrainTrace(userQuery: string, brainRoot: string, opti
|
|||||||
} = {}): SecondBrainTrace {
|
} = {}): SecondBrainTrace {
|
||||||
const query = userQuery.trim();
|
const query = userQuery.trim();
|
||||||
const shouldUseSecondBrain = !!options.force || shouldUseBrain(query);
|
const shouldUseSecondBrain = !!options.force || shouldUseBrain(query);
|
||||||
const retrievalQuery = buildRetrievalQuery(query);
|
const queryIntent = classifyQueryIntent(query);
|
||||||
|
const retrievalQuery = buildRetrievalQuery(query, queryIntent);
|
||||||
const baseTrace: SecondBrainTrace = {
|
const baseTrace: SecondBrainTrace = {
|
||||||
userQuery: query,
|
userQuery: query,
|
||||||
|
queryIntent,
|
||||||
shouldUseSecondBrain,
|
shouldUseSecondBrain,
|
||||||
secondBrainUsed: false,
|
secondBrainUsed: false,
|
||||||
reason: shouldUseSecondBrain
|
reason: shouldUseSecondBrain
|
||||||
@@ -66,7 +70,7 @@ export function buildSecondBrainTrace(userQuery: string, brainRoot: string, opti
|
|||||||
const files = findBrainFiles(brainRoot)
|
const files = findBrainFiles(brainRoot)
|
||||||
.filter((file) => includeRaw || !isRawConversationPath(path.relative(brainRoot, file)));
|
.filter((file) => includeRaw || !isRawConversationPath(path.relative(brainRoot, file)));
|
||||||
const terms = tokenize(retrievalQuery);
|
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)
|
.filter((doc) => doc.score >= 0.25)
|
||||||
.sort((a, b) => b.score - a.score)
|
.sort((a, b) => b.score - a.score)
|
||||||
.slice(0, options.limit || 5);
|
.slice(0, options.limit || 5);
|
||||||
@@ -134,6 +138,7 @@ export function renderSecondBrainTraceContext(trace: SecondBrainTrace): string {
|
|||||||
return [
|
return [
|
||||||
'[SECOND BRAIN TRACE]',
|
'[SECOND BRAIN TRACE]',
|
||||||
`Second Brain used: ${trace.secondBrainUsed ? 'yes' : 'no'}`,
|
`Second Brain used: ${trace.secondBrainUsed ? 'yes' : 'no'}`,
|
||||||
|
`Query intent: ${trace.queryIntent}`,
|
||||||
`Retrieval query: ${trace.retrievalQuery}`,
|
`Retrieval query: ${trace.retrievalQuery}`,
|
||||||
`Reason: ${trace.reason}`,
|
`Reason: ${trace.reason}`,
|
||||||
docs ? `Selected notes:\n${docs}` : 'Selected notes: none',
|
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.',
|
'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.',
|
'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.',
|
'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
|
hasProjectEvidence
|
||||||
? 'At least one selected note can support project-specific claims.'
|
? 'At least one selected note can support project-specific claims.'
|
||||||
: 'No selected note can support project-specific implementation claims.',
|
: 'No selected note can support project-specific implementation claims.',
|
||||||
@@ -189,6 +200,9 @@ export function renderSecondBrainTraceMarkdown(trace: SecondBrainTrace, debug: b
|
|||||||
'## 2nd Brain 사용 여부',
|
'## 2nd Brain 사용 여부',
|
||||||
status,
|
status,
|
||||||
'',
|
'',
|
||||||
|
'## 질문 의도',
|
||||||
|
trace.queryIntent,
|
||||||
|
'',
|
||||||
'## 이유',
|
'## 이유',
|
||||||
trace.reason,
|
trace.reason,
|
||||||
'',
|
'',
|
||||||
@@ -214,6 +228,7 @@ export function renderSecondBrainTraceMarkdown(trace: SecondBrainTrace, debug: b
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
secondBrainUsed: trace.secondBrainUsed,
|
secondBrainUsed: trace.secondBrainUsed,
|
||||||
shouldUseSecondBrain: trace.shouldUseSecondBrain,
|
shouldUseSecondBrain: trace.shouldUseSecondBrain,
|
||||||
|
queryIntent: trace.queryIntent,
|
||||||
retrievalQuery: trace.retrievalQuery,
|
retrievalQuery: trace.retrievalQuery,
|
||||||
searchedCollections: trace.searchedCollections,
|
searchedCollections: trace.searchedCollections,
|
||||||
retrievedDocuments: trace.retrievedDocuments.map((doc) => ({
|
retrievedDocuments: trace.retrievedDocuments.map((doc) => ({
|
||||||
@@ -311,11 +326,35 @@ function deriveProjectClaimPolicy(
|
|||||||
|
|
||||||
function shouldUseBrain(query: string): boolean {
|
function shouldUseBrain(query: string): boolean {
|
||||||
const normalized = query.toLowerCase();
|
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 {
|
function classifyQueryIntent(query: string): SecondBrainQueryIntent {
|
||||||
return tokenize(query).slice(0, 16).join(' ');
|
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[] {
|
function tokenize(value: string): string[] {
|
||||||
@@ -331,7 +370,7 @@ function tokenize(value: string): string[] {
|
|||||||
.filter((term) => term.length >= 2 && !stopWords.has(term));
|
.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 relative = path.relative(brainRoot, file);
|
||||||
const title = path.basename(file, path.extname(file));
|
const title = path.basename(file, path.extname(file));
|
||||||
const basename = relative.toLowerCase();
|
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 canSupportProjectClaim = sourceType === 'Project Evidence' || sourceType === 'User Decision';
|
||||||
|
|
||||||
const lower = content.toLowerCase();
|
const lower = content.toLowerCase();
|
||||||
let score = pathPriority(relative);
|
let score = pathPriority(relative, intent);
|
||||||
for (const term of terms) {
|
for (const term of terms) {
|
||||||
if (basename.includes(term)) score += 4;
|
if (basename.includes(term)) score += 4;
|
||||||
const matches = lower.split(term).length - 1;
|
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);
|
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();
|
const normalized = relativePath.toLowerCase();
|
||||||
let score = 0;
|
let score = 0;
|
||||||
if (/(^|[\\/])(decisions?|adr|planning|development|bugs|retrospectives|records)([\\/]|$)/i.test(normalized)) {
|
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)) {
|
if (/(^|[\\/])index(_\d+)?\.md$/i.test(normalized) || /[\\/]index\.md$/i.test(normalized)) {
|
||||||
score -= 2;
|
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;
|
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 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 {
|
.markdown-body table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
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.
|
- 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.
|
- 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.
|
- 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.
|
- Prefer paragraph-style formatting over bullet-heavy formatting. Do not put asterisks or dash bullets at the start of most lines.
|
||||||
- Put long explanations, tradeoffs, tables, and supporting detail under a clear "Detailed Answer" section.
|
- 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.
|
- 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.
|
- 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.
|
- 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.
|
- 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.
|
- 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.
|
- 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:
|
Available action tags:
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,16 @@ describe('buildProjectChronicleGuardContext', () => {
|
|||||||
expect(context).toContain('Project selection status: selected');
|
expect(context).toContain('Project selection status: selected');
|
||||||
expect(context).toContain('Short conclusion first');
|
expect(context).toContain('Short conclusion first');
|
||||||
expect(context).toContain('Brief summary');
|
expect(context).toContain('Brief summary');
|
||||||
|
expect(context).toContain('one compact paragraph by default');
|
||||||
expect(context).toContain('Detailed answer');
|
expect(context).toContain('Detailed answer');
|
||||||
|
expect(context).toContain('Avoid bullet-heavy formatting');
|
||||||
|
expect(context).toContain('Use visible markdown headings');
|
||||||
expect(context).toContain('No Evidence, No Project Claim');
|
expect(context).toContain('No Evidence, No Project Claim');
|
||||||
expect(context).toContain('confirmed facts, inferences, general knowledge, and needs verification');
|
expect(context).toContain('confirmed facts, inferences, general knowledge, and needs verification');
|
||||||
expect(context).toContain('현재 정보만으로는 기술 구조를 판단할 수 없습니다');
|
expect(context).toContain('현재 정보만으로는 기술 구조를 판단할 수 없습니다');
|
||||||
expect(context).toContain('technically stable');
|
expect(context).toContain('technically stable');
|
||||||
|
expect(context).toContain('approval likelihood');
|
||||||
|
expect(context).toContain('confirmed facts, inference, general UX/business principle, needs verification, recommended direction');
|
||||||
expect(context).toContain('Project record target check');
|
expect(context).toContain('Project record target check');
|
||||||
expect(context).toContain('Record path check');
|
expect(context).toContain('Record path check');
|
||||||
expect(context).toContain('Question reason');
|
expect(context).toContain('Question reason');
|
||||||
|
|||||||
@@ -40,6 +40,17 @@ describe('Second Brain Trace', () => {
|
|||||||
].join('\n'),
|
].join('\n'),
|
||||||
'utf8'
|
'utf8'
|
||||||
);
|
);
|
||||||
|
fs.mkdirSync(path.join(brainRoot, 'UX'), { recursive: true });
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(brainRoot, 'UX', 'Customer Journey Virtual Store.md'),
|
||||||
|
[
|
||||||
|
'# Customer Journey Virtual Store',
|
||||||
|
'',
|
||||||
|
'Customer-facing virtual stores should connect spatial experience to product discovery, product understanding, and purchase conversion.',
|
||||||
|
'Stakeholder approval often depends on requirement fit, business value, and acceptance criteria rather than visual novelty alone.'
|
||||||
|
].join('\n'),
|
||||||
|
'utf8'
|
||||||
|
);
|
||||||
fs.mkdirSync(path.join(brainRoot, '00_Raw', 'conversations'), { recursive: true });
|
fs.mkdirSync(path.join(brainRoot, '00_Raw', 'conversations'), { recursive: true });
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(brainRoot, '00_Raw', 'conversations', '2026-05-01.md'),
|
path.join(brainRoot, '00_Raw', 'conversations', '2026-05-01.md'),
|
||||||
@@ -189,4 +200,19 @@ describe('Second Brain Trace', () => {
|
|||||||
fs.rmSync(root, { recursive: true, force: true });
|
fs.rmSync(root, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('prioritizes UX and business documents for approval and customer-experience questions', () => {
|
||||||
|
const trace = buildSecondBrainTrace(
|
||||||
|
'롯데 이노베이트가 고객 대상 버추얼 웹스토어에서 상품 중심이 아니라 공간 중심 개발 방향을 승인할 가능성이 있을까?',
|
||||||
|
brainRoot,
|
||||||
|
{ force: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(trace.queryIntent).toBe('ux-business');
|
||||||
|
expect(trace.retrievalQuery).toContain('customer journey');
|
||||||
|
expect(trace.retrievalQuery).toContain('approval');
|
||||||
|
expect(trace.retrievedDocuments[0].path).toContain('Customer Journey Virtual Store.md');
|
||||||
|
expect(trace.retrievedDocuments[0].path).not.toContain('API Gateway.md');
|
||||||
|
expect(renderSecondBrainTraceContext(trace)).toContain('Approval likelihood is an inference');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user