Version 2.54.0 Release: Jarvis Project Brief and Thinking Partner Response Contract

This commit is contained in:
g1nation
2026-05-03 20:33:44 +09:00
parent 9c242a5b8d
commit d8ae0b5964
3 changed files with 117 additions and 3 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "g1nation", "name": "g1nation",
"displayName": "G1nation", "displayName": "G1nation",
"description": "High-performance autonomous local AI coding agent for VS Code. Features vectorized inference, asynchronous task management, and 100% offline processing.", "description": "High-performance autonomous local AI coding agent for VS Code. Features vectorized inference, asynchronous task management, and 100% offline processing.",
"version": "2.53.0", "version": "2.54.0",
"publisher": "connectailab", "publisher": "connectailab",
"license": "MIT", "license": "MIT",
"icon": "assets/icon.png", "icon": "assets/icon.png",
+67 -2
View File
@@ -287,6 +287,12 @@ export class AgentExecutor {
if (recentProjectKnowledgeContext) { if (recentProjectKnowledgeContext) {
contextBlock += `\n\n${recentProjectKnowledgeContext}`; contextBlock += `\n\n${recentProjectKnowledgeContext}`;
} }
const projectBriefContext = prompt && loopDepth === 0
? this.buildJarvisProjectBriefContext(prompt, localPathContext, recentProjectKnowledgeContext)
: '';
if (projectBriefContext) {
contextBlock += `\n\n${projectBriefContext}`;
}
// 2. Setup History // 2. Setup History
if (prompt !== null) { if (prompt !== null) {
@@ -339,12 +345,15 @@ export class AgentExecutor {
const localProjectKnowledgeCtx = prompt && localPathContext && this.isProjectKnowledgeCreationRequest(prompt) const localProjectKnowledgeCtx = prompt && localPathContext && this.isProjectKnowledgeCreationRequest(prompt)
? `\n\n[LOCAL PROJECT KNOWLEDGE CREATION OVERRIDE]\nThe user gave an accessible local project path and asked to create project knowledge. Do not ask blocking scope questions. Use a sensible default MVP: create or propose a project overview note from the inspected tree and priority file previews. If writing is not explicitly safe, provide the concrete note draft and target path.` ? `\n\n[LOCAL PROJECT KNOWLEDGE CREATION OVERRIDE]\nThe user gave an accessible local project path and asked to create project knowledge. Do not ask blocking scope questions. Use a sensible default MVP: create or propose a project overview note from the inspected tree and priority file previews. If writing is not explicitly safe, provide the concrete note draft and target path.`
: ''; : '';
const thinkingPartnerCtx = prompt && this.isThinkingPartnerRequest(prompt)
? `\n\n[JARVIS THINKING PARTNER MODE]\nThe user is using this tool to clarify project direction, not just to receive generic advice. Give a clear opinionated verdict first. Then separate confirmed facts, inferences, concerns, decision forks, and the next small action. Do not merely say the direction is good. If evidence is thin, say exactly what is missing and what file or record should be checked next.`
: '';
const secondBrainTraceCtx = secondBrainTrace const secondBrainTraceCtx = secondBrainTrace
? `\n\n${renderSecondBrainTraceContext(secondBrainTrace)}` ? `\n\n${renderSecondBrainTraceContext(secondBrainTrace)}`
: ''; : '';
const memoryCtx = this.buildMemoryContext(prompt || '', activeBrain); const memoryCtx = this.buildMemoryContext(prompt || '', activeBrain);
const fullSystemPrompt = `${agentSkillCtx}\n\n${systemPrompt}${internetCtx}${memoryCtx}${designerCtx}${localProjectKnowledgeCtx}${secondBrainTraceCtx}\n\n[CONTEXT]\n${brainContext}${brainInventoryCtx}\n${contextBlock}${negativeCtx}`; const fullSystemPrompt = `${agentSkillCtx}\n\n${systemPrompt}${internetCtx}${memoryCtx}${designerCtx}${localProjectKnowledgeCtx}${thinkingPartnerCtx}${secondBrainTraceCtx}\n\n[CONTEXT]\n${brainContext}${brainInventoryCtx}\n${contextBlock}${negativeCtx}`;
const messagesForRequest: ChatMessage[] = [ const messagesForRequest: ChatMessage[] = [
{ role: 'system', content: fullSystemPrompt, internal: true }, { role: 'system', content: fullSystemPrompt, internal: true },
...reqMessages ...reqMessages
@@ -766,7 +775,7 @@ export class AgentExecutor {
} }
private shouldPreflightLocalProjectPath(prompt: string): boolean { private shouldPreflightLocalProjectPath(prompt: string): boolean {
return /(검토|리뷰|분석|확인|봐줘|고쳐|개선|디버그|지식|문서화|문서|정리|기록|위키|저장|만들|생성|knowledge|document|documentation|wiki|summari[sz]e|review|analy[sz]e|inspect|debug|fix|improve)/i.test(prompt) return /(검토|리뷰|분석|확인|봐줘|고쳐|개선|디버그|지식|문서화|문서|정리|기록|위키|저장|만들|생성|설계|아키텍처|구조|방향|의견|생각|판단|어떤\s*거?\s*같|어때|knowledge|document|documentation|wiki|summari[sz]e|review|analy[sz]e|inspect|debug|fix|improve|architecture|design|structure|opinion|think|judge)/i.test(prompt)
&& /\/Volumes\/Data\/project\/Antigravity\/[^\s`"'<>]+/i.test(prompt); && /\/Volumes\/Data\/project\/Antigravity\/[^\s`"'<>]+/i.test(prompt);
} }
@@ -779,6 +788,62 @@ export class AgentExecutor {
return /(아키텍처|구조|조사|분석|설계|흐름|모듈|역할|개선|architecture|structure|design|flow|module|investigate|analy[sz]e)/i.test(prompt); return /(아키텍처|구조|조사|분석|설계|흐름|모듈|역할|개선|architecture|structure|design|flow|module|investigate|analy[sz]e)/i.test(prompt);
} }
private isThinkingPartnerRequest(prompt: string): boolean {
return /(어떤\s*거?\s*같|어때|어떻게\s*생각|의견|판단|방향|설계|아키텍처|구조|자비스|생각.*정리|갈림길|architecture|design|direction|opinion|think|judge)/i.test(prompt);
}
private buildJarvisProjectBriefContext(prompt: string, localPathContext: string, recentProjectKnowledgeContext: string): string {
if (!this.isThinkingPartnerRequest(prompt)) {
return '';
}
const sourceContext = localPathContext && localPathContext.includes('Access: succeeded')
? localPathContext
: recentProjectKnowledgeContext;
if (!sourceContext) {
return [
'[JARVIS PROJECT BRIEF]',
'No concrete local project brief is available yet.',
'Use the conversation and Second Brain cautiously. If the user asks about a project architecture, ask for or inspect the project path before making strong claims.',
'',
this.buildThinkingPartnerResponseContract()
].join('\n');
}
const projectPath = sourceContext.match(/Path:\s*(.+)/)?.[1]?.trim()
|| sourceContext.match(/Repository:\s*`([^`]+)`/)?.[1]?.trim()
|| sourceContext.match(/project evidence:\s*([^\s]+)/i)?.[1]?.trim()
|| 'current project';
const evidenceFiles = sourceContext.includes('Priority file previews:')
? this.extractPriorityPreviewFiles(sourceContext).slice(0, 10)
: this.extractEvidenceFilesFromProjectKnowledge(sourceContext).slice(0, 10);
const treeMatch = sourceContext.match(/Scanned tree:\n([\s\S]*?)(?:\nPriority file previews:|$)/);
const treePreview = treeMatch?.[1]?.trim().split('\n').slice(0, 30).join('\n') || '';
return [
'[JARVIS PROJECT BRIEF]',
`Project evidence target: ${projectPath}`,
evidenceFiles.length
? `Evidence files available:\n${evidenceFiles.map((file) => `- ${file}`).join('\n')}`
: 'Evidence files available: not enough concrete file markers were found.',
treePreview ? `Visible structure preview:\n${treePreview}` : '',
'',
this.buildThinkingPartnerResponseContract()
].filter(Boolean).join('\n');
}
private buildThinkingPartnerResponseContract(): string {
return [
'Thinking partner response contract:',
'1. Start with a direct verdict, not a generic compliment.',
'2. Separate confirmed facts from inferences.',
'3. Name the strongest part of the direction and the weakest/missing part.',
'4. Identify the real decision fork the user is facing.',
'5. Suggest one small next action that would make the project direction clearer.',
'6. If project evidence is thin, say what must be inspected next instead of pretending certainty.'
].join('\n');
}
private buildRequestHistory(history: ChatMessage[]): ChatMessage[] { private buildRequestHistory(history: ChatMessage[]): ChatMessage[] {
return history.map((message) => { return history.map((message) => {
if (message.role !== 'assistant' || typeof message.content !== 'string') { if (message.role !== 'assistant' || typeof message.content !== 'string') {
+49
View File
@@ -70,6 +70,19 @@ describe('local project path preflight', () => {
expect(agent.shouldPreflightLocalProjectPath(prompt)).toBe(true); expect(agent.shouldPreflightLocalProjectPath(prompt)).toBe(true);
}); });
it('treats architecture opinion requests with local paths as inspectable work', () => {
const context: any = {
globalStorageUri: { fsPath: path.join(root, '.storage') },
workspaceState: stateStore(),
globalState: stateStore()
};
const agent = new AgentExecutor(context) as any;
const prompt = '프로젝트 경로는 /Volumes/Data/project/Antigravity/ConnectAI 이야. 그럼 이 프로젝트에 대한 설계, 아키텍처는 어떤거 같아?';
expect(agent.shouldPreflightLocalProjectPath(prompt)).toBe(true);
expect(agent.isThinkingPartnerRequest(prompt)).toBe(true);
});
it('removes file-structure requests when knowledge creation path access already succeeded', () => { it('removes file-structure requests when knowledge creation path access already succeeded', () => {
const context: any = { const context: any = {
globalStorageUri: { fsPath: path.join(root, '.storage') }, globalStorageUri: { fsPath: path.join(root, '.storage') },
@@ -299,4 +312,40 @@ describe('local project path preflight', () => {
expect(fixed).toContain('`src/agent.ts`'); expect(fixed).toContain('`src/agent.ts`');
expect(fixed).toContain('로컬 프로젝트 경로'); expect(fixed).toContain('로컬 프로젝트 경로');
}); });
it('builds a Jarvis project brief for architecture thinking-partner questions', () => {
const context: any = {
globalStorageUri: { fsPath: path.join(root, '.storage') },
workspaceState: stateStore(),
globalState: stateStore()
};
const agent = new AgentExecutor(context) as any;
const localPathContext = [
'Path: /Volumes/Data/project/Antigravity/ConnectAI',
'Access: succeeded',
'Type: directory',
'Scanned tree:',
'package.json',
'src/agent.ts',
'src/features/secondBrainTrace.ts',
'Priority file previews:',
'File: package.json',
'{"name":"connectai"}',
'File: src/agent.ts',
'export class AgentExecutor {}'
].join('\n');
const brief = agent.buildJarvisProjectBriefContext(
'그럼 이 프로젝트에 대한 설계, 아키텍처는 어떤거 같아?',
localPathContext,
''
);
expect(brief).toContain('[JARVIS PROJECT BRIEF]');
expect(brief).toContain('/Volumes/Data/project/Antigravity/ConnectAI');
expect(brief).toContain('src/agent.ts');
expect(brief).toContain('Thinking partner response contract');
expect(brief).toContain('direct verdict');
expect(brief).toContain('decision fork');
});
}); });