feat(engine): implement self-reflection (reflector) stage in multi-agent pipeline
- Added ReflectorAgent for meta-cognition and critical review between Research and Writing - Updated WriterAgent to explicitly address reflection critiques - Introduced 'g1nation.enableReflection' configuration setting - Added comprehensive integration tests for the self-reflection stage - Documented design decisions in ADR-0010 and related discussion records
This commit is contained in:
@@ -3,23 +3,23 @@
|
|||||||
<!-- ASTRA:AUTO-START -->
|
<!-- ASTRA:AUTO-START -->
|
||||||
|
|
||||||
## Snapshot
|
## Snapshot
|
||||||
- **Workspace**: `ConnectAI` `v2.0.2` _(absolute path varies by environment; resolved from the active VS Code workspace)_
|
- **Workspace**: `ConnectAI` `v2.0.9` _(absolute path varies by environment; resolved from the active VS Code workspace)_
|
||||||
- **Description**: The personal intelligence layer for Antigravity and VS Code. A private cognitive partner for deep project context, memory, and proactive strategic decision-making.
|
- **Description**: The personal intelligence layer for Antigravity and VS Code. A private cognitive partner for deep project context, memory, and proactive strategic decision-making.
|
||||||
- **Stack**: TypeScript, Node.js, VS Code Extension, LM Studio SDK, Test runner
|
- **Stack**: TypeScript, Node.js, VS Code Extension, LM Studio SDK, Test runner
|
||||||
- **Stats**: 184 source files, ~31,651 lines across 5 top-level modules.
|
- **Stats**: 201 source files, ~35,737 lines across 5 top-level modules.
|
||||||
|
|
||||||
## Last Refresh
|
## Last Refresh
|
||||||
- **Time**: 2026-05-13T13:48:21.458Z
|
- **Time**: 2026-05-13T16:44:14.023Z
|
||||||
- **Files newly analysed**: 3
|
- **Files newly analysed**: 8
|
||||||
- **Files reused from cache**: 181
|
- **Files reused from cache**: 193
|
||||||
|
|
||||||
## Directory Map
|
## Directory Map
|
||||||
```mermaid
|
```mermaid
|
||||||
mindmap
|
mindmap
|
||||||
root((ConnectAI))
|
root((ConnectAI))
|
||||||
src/
|
src/
|
||||||
core/
|
|
||||||
features/
|
features/
|
||||||
|
core/
|
||||||
memory/
|
memory/
|
||||||
retrieval/
|
retrieval/
|
||||||
docs/
|
docs/
|
||||||
@@ -37,11 +37,11 @@ mindmap
|
|||||||
> Arrows: which top-level module imports from which.
|
> Arrows: which top-level module imports from which.
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart LR
|
flowchart LR
|
||||||
src["src/<br/>85 files"]
|
src["src/<br/>100 files"]
|
||||||
media["media/<br/>6 files"]
|
media["media/<br/>6 files"]
|
||||||
tests["tests/<br/>27 files"]
|
tests["tests/<br/>27 files"]
|
||||||
core_py["core_py/<br/>6 files"]
|
core_py["core_py/<br/>6 files"]
|
||||||
docs["docs/<br/>60 files"]
|
docs["docs/<br/>62 files"]
|
||||||
tests --> src
|
tests --> src
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -53,78 +53,78 @@ flowchart LR
|
|||||||
|
|
||||||
## Hub Files
|
## Hub Files
|
||||||
> Imported by many other files — touching these has wide blast radius.
|
> Imported by many other files — touching these has wide blast radius.
|
||||||
- `src/utils.ts` — referenced by **37** files
|
- `src/utils.ts` — referenced by **43** files
|
||||||
- `src/config.ts` — referenced by **11** files
|
- `src/config.ts` — referenced by **12** files
|
||||||
- `src/lib/paths.ts` — referenced by **10** files
|
- `src/lib/paths.ts` — referenced by **10** files
|
||||||
|
- `src/features/company/types.ts` — referenced by **9** files · Type definitions for the 1인 기업 (One-Person Company) mode. The mode turns the user into a virtual CEO that dispatches work to a roster of specialist agents. Each turn produces a session directory conta
|
||||||
|
- `src/features/company/agents.ts` — referenced by **7** files · The 9-agent roster for 1인 기업 모드. Each entry is a static description — persona, role, specialty — used to build the specialist's system prompt at dispatch time. The set was adopted from Connectorigin's
|
||||||
|
- `src/skills/agentKnowledgeMap.ts` — referenced by **6** files
|
||||||
- `src/lib/engine.ts` — referenced by **6** files
|
- `src/lib/engine.ts` — referenced by **6** files
|
||||||
- `src/sidebarProvider.ts` — referenced by **6** files
|
- `src/core/services.ts` — referenced by **6** files
|
||||||
- `src/retrieval/scoring.ts` — referenced by **6** files · Scoring Engine — TF-IDF + Bilingual Tokenizer 단순 includes() 키워드 매칭을 넘어서, TF-IDF 가중치 기반의 문서 스코어링을 제공합니다. 한국어/영어 양국어 토크나이저를 포함합니다.
|
|
||||||
- `src/memory/types.ts` — referenced by **6** files · Memory Type Definitions (메모리 타입 정의) Astra의 5-Layer Cognitive Memory System의 모든 타입을 정의합니다. ① Short-Term ② Long-Term ③ Project ④ Procedural ⑤ Episodic
|
|
||||||
- `src/retrieval/lessonHelpers.ts` — referenced by **5** files · Lesson / Experience Memory — pure helpers (no vscode dependency) "Lesson" = a markdown file in the active brain that captures a past mistake/risk and how to avoid repeating it. Identified by a lessons
|
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
### `src/` — 85 files, ~20,591 lines
|
### `src/` — 100 files, ~23,711 lines
|
||||||
|
|
||||||
**Sub-directories**
|
**Sub-directories**
|
||||||
|
- `src/features/` (28) — The 9-agent roster for 1인 기업 모드. Each entry is a static description — persona, role, specialty — used to build the speci
|
||||||
- `src/core/` (15) — Astra Path Resolver (경로 해결기) Astra의 모든 데이터 파일(.astra 디렉토리)의 경로를 중앙에서 관리합니다. 확장 프로그램의 설치 경로(extensionUri) 기반으로 .astra 디렉토
|
- `src/core/` (15) — Astra Path Resolver (경로 해결기) Astra의 모든 데이터 파일(.astra 디렉토리)의 경로를 중앙에서 관리합니다. 확장 프로그램의 설치 경로(extensionUri) 기반으로 .astra 디렉토
|
||||||
- `src/features/` (14) — Project Architecture Context (Feature 2) Builds a markdown document that captures the durable facts about a project — it
|
|
||||||
- `src/memory/` (8) — Episodic Memory (일화 기억) 과거 대화/회의/결정의 맥락 흐름을 저장합니다. 세션 종료 시 자동으로 에피소드를 요약하여 저장합니다. "왜 이렇게 결정했는지", "어떤 흐름으로 진행했는지" 기록. 저장
|
- `src/memory/` (8) — Episodic Memory (일화 기억) 과거 대화/회의/결정의 맥락 흐름을 저장합니다. 세션 종료 시 자동으로 에피소드를 요약하여 저장합니다. "왜 이렇게 결정했는지", "어떤 흐름으로 진행했는지" 기록. 저장
|
||||||
- `src/retrieval/` (8) — Brain Index — persistent, mtime-keyed tokenized cache of the Second Brain RAG 검색은 매 질의마다 브레인의 모든 .md 파일을 읽고 토크나이즈해서 TF-I
|
- `src/retrieval/` (8) — Brain Index — persistent, mtime-keyed tokenized cache of the Second Brain RAG 검색은 매 질의마다 브레인의 모든 .md 파일을 읽고 토크나이즈해서 TF-I
|
||||||
- `src/docs/` (6) — src Chronicle Records
|
- `src/docs/` (6) — src Chronicle Records
|
||||||
- `src/lib/` (6) — Context Manager (컨텍스트 한계 관리) "context length = 132k" 는 "답변을 132k 토큰까지 생성해도 된다" 가 아닙니다. 시스템 프롬프트 + 대화 기록 + 입력 문서 + 생성될 답변
|
- `src/lib/` (6) — Context Manager (컨텍스트 한계 관리) "context length = 132k" 는 "답변을 132k 토큰까지 생성해도 된다" 가 아닙니다. 시스템 프롬프트 + 대화 기록 + 입력 문서 + 생성될 답변
|
||||||
|
- `src/integrations/` (4) — Per-chat conversation history for the Telegram bot. Why this exists: the previous bot was stateless — every inbound mess
|
||||||
- `src/lmstudio/` (4) — 4 files (.ts)
|
- `src/lmstudio/` (4) — 4 files (.ts)
|
||||||
- `src/sidebar/` (4) — 4 files (.ts)
|
- `src/sidebar/` (4) — 4 files (.ts)
|
||||||
- `src/skills/` (4) — 4 files (.ts)
|
- `src/skills/` (4) — 4 files (.ts)
|
||||||
- `src/integrations/` (3) — Subset of the Telegram Bot API types we actually consume. Source: https://core.telegram.org/bots/api Only fields the bot
|
|
||||||
- `src/agents/` (2) — 2 files (.ts)
|
- `src/agents/` (2) — 2 files (.ts)
|
||||||
- `src/scaffolder/` (2) — Scaffolder template catalog. Templates are pure data — (projectName) => { [relativePath]: contents }. New templates are
|
- `src/scaffolder/` (2) — Scaffolder template catalog. Templates are pure data — (projectName) => { [relativePath]: contents }. New templates are
|
||||||
|
|
||||||
**Key files**
|
**Key files**
|
||||||
- `src/utils.ts` (268 lines)
|
- `src/utils.ts` (268 lines)
|
||||||
- `src/config.ts` (209 lines)
|
- `src/config.ts` (216 lines)
|
||||||
|
- `src/features/company/types.ts` (150 lines) — Type definitions for the 1인 기업 (One-Person Company) mode. The mode turns the user into a virtual CEO that dispatches work to a roster of specialist agents. Each turn produces a session directory conta
|
||||||
- `src/lib/paths.ts` (151 lines)
|
- `src/lib/paths.ts` (151 lines)
|
||||||
- `src/sidebarProvider.ts` (2603 lines)
|
- `src/sidebarProvider.ts` (2934 lines)
|
||||||
|
- `src/features/company/agents.ts` (136 lines) — The 9-agent roster for 1인 기업 모드. Each entry is a static description — persona, role, specialty — used to build the specialist's system prompt at dispatch time. The set was adopted from Connectorigin's
|
||||||
- `src/memory/types.ts` (126 lines) — Memory Type Definitions (메모리 타입 정의) Astra의 5-Layer Cognitive Memory System의 모든 타입을 정의합니다. ① Short-Term ② Long-Term ③ Project ④ Procedural ⑤ Episodic
|
- `src/memory/types.ts` (126 lines) — Memory Type Definitions (메모리 타입 정의) Astra의 5-Layer Cognitive Memory System의 모든 타입을 정의합니다. ① Short-Term ② Long-Term ③ Project ④ Procedural ⑤ Episodic
|
||||||
- `src/retrieval/scoring.ts` (518 lines) — Scoring Engine — TF-IDF + Bilingual Tokenizer 단순 includes() 키워드 매칭을 넘어서, TF-IDF 가중치 기반의 문서 스코어링을 제공합니다. 한국어/영어 양국어 토크나이저를 포함합니다.
|
- `src/retrieval/scoring.ts` (518 lines) — Scoring Engine — TF-IDF + Bilingual Tokenizer 단순 includes() 키워드 매칭을 넘어서, TF-IDF 가중치 기반의 문서 스코어링을 제공합니다. 한국어/영어 양국어 토크나이저를 포함합니다.
|
||||||
- `src/skills/agentKnowledgeMap.ts` (374 lines)
|
- `src/skills/agentKnowledgeMap.ts` (374 lines)
|
||||||
- `src/agent.ts` (3207 lines)
|
- `src/core/services.ts` (164 lines)
|
||||||
|
- `src/agent.ts` (3232 lines)
|
||||||
|
- `src/features/company/companyConfig.ts` (330 lines) — State + config plumbing for 1인 기업 모드. Two surfaces: - CompanyState (runtime data: enabled flag, company name, which agents are active, per-agent model overrides). Persisted in VS Code's globalState so
|
||||||
- `src/retrieval/lessonHelpers.ts` (325 lines) — Lesson / Experience Memory — pure helpers (no vscode dependency) "Lesson" = a markdown file in the active brain that captures a past mistake/risk and how to avoid repeating it. Identified by a lessons
|
- `src/retrieval/lessonHelpers.ts` (325 lines) — Lesson / Experience Memory — pure helpers (no vscode dependency) "Lesson" = a markdown file in the active brain that captures a past mistake/risk and how to avoid repeating it. Identified by a lessons
|
||||||
- `src/lib/engine.ts` (849 lines)
|
- `src/lib/engine.ts` (880 lines)
|
||||||
- `src/features/approval/approvalQueue.ts` (129 lines)
|
- `src/features/approval/approvalQueue.ts` (129 lines)
|
||||||
|
- `src/integrations/telegram/telegramClient.ts` (154 lines)
|
||||||
- `src/features/projectArchitecture/scanner.ts` (644 lines) — Deep static analyser for the Project Architecture Context generator. Walks the project tree (skipping the usual nodemodules / out / dist noise), pulls the role of each interesting file from its leadin
|
- `src/features/projectArchitecture/scanner.ts` (644 lines) — Deep static analyser for the Project Architecture Context generator. Walks the project tree (skipping the usual nodemodules / out / dist noise), pulls the role of each interesting file from its leadin
|
||||||
- `src/lib/contextManager.ts` (275 lines) — Context Manager (컨텍스트 한계 관리) "context length = 132k" 는 "답변을 132k 토큰까지 생성해도 된다" 가 아닙니다. 시스템 프롬프트 + 대화 기록 + 입력 문서 + 생성될 답변 + 여유분 ≤ context length 이 모듈은 요청을 보내기 전에 입력 토큰을 추정하고, - 동적으로 출력 상한(maxTokens)을 계
|
- `src/lib/contextManager.ts` (275 lines) — Context Manager (컨텍스트 한계 관리) "context length = 132k" 는 "답변을 132k 토큰까지 생성해도 된다" 가 아닙니다. 시스템 프롬프트 + 대화 기록 + 입력 문서 + 생성될 답변 + 여유분 ≤ context length 이 모듈은 요청을 보내기 전에 입력 토큰을 추정하고, - 동적으로 출력 상한(maxTokens)을 계
|
||||||
- `src/core/astraPath.ts` (50 lines) — Astra Path Resolver (경로 해결기) Astra의 모든 데이터 파일(.astra 디렉토리)의 경로를 중앙에서 관리합니다. 확장 프로그램의 설치 경로(extensionUri) 기반으로 .astra 디렉토리를 해결하여, 사용자 프로젝트 루트가 아닌 ConnectAI 패키지 내부에 데이터를 저장합니다. 이 모듈은 AAL(Astra Autonomou
|
- `src/core/astraPath.ts` (50 lines) — Astra Path Resolver (경로 해결기) Astra의 모든 데이터 파일(.astra 디렉토리)의 경로를 중앙에서 관리합니다. 확장 프로그램의 설치 경로(extensionUri) 기반으로 .astra 디렉토리를 해결하여, 사용자 프로젝트 루트가 아닌 ConnectAI 패키지 내부에 데이터를 저장합니다. 이 모듈은 AAL(Astra Autonomou
|
||||||
|
- `src/extension.ts` (945 lines)
|
||||||
- `src/features/projectChronicle/types.ts` (118 lines)
|
- `src/features/projectChronicle/types.ts` (118 lines)
|
||||||
- `src/integrations/telegram/telegramClient.ts` (154 lines)
|
|
||||||
- `src/lmstudio/client.ts` (147 lines)
|
- `src/lmstudio/client.ts` (147 lines)
|
||||||
- `src/retrieval/brainIndex.ts` (325 lines) — Brain Index — persistent, mtime-keyed tokenized cache of the Second Brain RAG 검색은 매 질의마다 브레인의 모든 .md 파일을 읽고 토크나이즈해서 TF-IDF 점수를 계산했습니다 — 파일 수가 많아지면 그게 병목입니다. 이 모듈은 <brainPath>/.astra/brain-index.json 에
|
- `src/retrieval/brainIndex.ts` (325 lines) — Brain Index — persistent, mtime-keyed tokenized cache of the Second Brain RAG 검색은 매 질의마다 브레인의 모든 .md 파일을 읽고 토크나이즈해서 TF-IDF 점수를 계산했습니다 — 파일 수가 많아지면 그게 병목입니다. 이 모듈은 <brainPath>/.astra/brain-index.json 에
|
||||||
- `src/extension.ts` (757 lines)
|
- `src/features/company/promptBuilder.ts` (202 lines) — System-prompt construction for company-mode agents. Each specialist needs a prompt that includes: - Their identity (name, role, specialty) + optional persona. - The action-tag contract (<createfile>,
|
||||||
- `src/features/projectArchitecture/index.ts` (515 lines) — Project Architecture Context (Feature 2) Builds a markdown document that captures the durable facts about a project — its purpose, modules, key files, constraints, decisions — so Astra can attach it t
|
- `src/features/company/sessionStore.ts` (231 lines) — Disk persistence for company-mode session artefacts. Each company turn produces a timestamped directory: <workspaceRoot>/.astra/company/sessions/2026-05-13T21-29/ ├─ brief.md ← CEO's task decompositio
|
||||||
- `src/lmstudio/activityTracker.ts` (19 lines)
|
|
||||||
- `src/memory/EpisodicMemory.ts` (278 lines) — Episodic Memory (일화 기억) 과거 대화/회의/결정의 맥락 흐름을 저장합니다. 세션 종료 시 자동으로 에피소드를 요약하여 저장합니다. "왜 이렇게 결정했는지", "어떤 흐름으로 진행했는지" 기록. 저장 위치: {brainPath}/memory/episodes/.json
|
|
||||||
- `src/memory/LongTermMemory.ts` (243 lines) — Long-Term Memory (장기 기억) 사용자의 취향, 프로젝트 목표, 반복 규칙, 과거 결정 사항을 영구적으로 저장하고 관리합니다. 저장 위치: {brainPath}/memory/longterm.json
|
|
||||||
- `src/memory/ProjectMemory.ts` (212 lines) — Project Memory (프로젝트 기억) 프로젝트별 요구사항, 코드 구조, 아키텍처 결정, 버그 기록 등을 Astra 확장 프로그램 내부에 저장하고 관리합니다. 저장 위치: {ConnectAI}/.astra/projectmemory.json (기존: {projectRoot}/.astra/ → 변경됨)
|
|
||||||
- `src/retrieval/index.ts` (514 lines) — RetrievalOrchestrator — Unified RAG Pipeline Astra의 모든 검색 소스를 통합 관리하는 오케스트레이터입니다. 검색 흐름: ① Query Planning — 의도 분류 + 검색 전략 결정 ② Parallel Search — Brain + Memory + Project + Episode 동시 검색 ③ Result Fusio
|
|
||||||
|
|
||||||
### `media/` — 6 files, ~3,304 lines
|
### `media/` — 6 files, ~4,099 lines
|
||||||
|
|
||||||
**Key files**
|
**Key files**
|
||||||
- `media/sidebar.css` (987 lines) — Stylesheet
|
- `media/sidebar.css` (1225 lines) — Stylesheet
|
||||||
- `media/sidebar.js` (1388 lines)
|
- `media/sidebar.js` (1874 lines)
|
||||||
|
- `media/sidebar.html` (356 lines) — Astra
|
||||||
- `media/settings-panel.css` (210 lines) — Stylesheet
|
- `media/settings-panel.css` (210 lines) — Stylesheet
|
||||||
- `media/sidebar.html` (285 lines) — Astra
|
|
||||||
- `media/settings-panel.html` (164 lines) — Astra Settings
|
- `media/settings-panel.html` (164 lines) — Astra Settings
|
||||||
- `media/settings-panel.js` (270 lines)
|
- `media/settings-panel.js` (270 lines)
|
||||||
|
|
||||||
### `tests/` — 27 files, ~4,802 lines
|
### `tests/` — 27 files, ~4,932 lines
|
||||||
*Depends on*: `src/`
|
*Depends on*: `src/`
|
||||||
|
|
||||||
**Sub-directories**
|
**Sub-directories**
|
||||||
- `tests/mocks/` (1) — 1 files (.js)
|
- `tests/mocks/` (1) — 1 files (.js)
|
||||||
|
|
||||||
**Key files**
|
**Key files**
|
||||||
- `tests/agentEngine.test.ts` (646 lines) — AgentEngine Integration Tests & Performance Benchmarks 검증 대상: 1. ErrorClassifier — 오류 유형(Transient/Permanent/Abort) 자동 분류 2. ErrorRecoveryMatrix — 각 규칙이 의도한 대응 전략으로 매핑되는지 검증 3. resilientExecute — 지수 백
|
- `tests/agentEngine.test.ts` (776 lines) — AgentEngine Integration Tests & Performance Benchmarks 검증 대상: 1. ErrorClassifier — 오류 유형(Transient/Permanent/Abort) 자동 분류 2. ErrorRecoveryMatrix — 각 규칙이 의도한 대응 전략으로 매핑되는지 검증 3. resilientExecute — 지수 백
|
||||||
- `tests/lmStudioLifecycle.test.ts` (318 lines) — Unit tests for ModelLifecycleManager. Strategy: inject mock ILMStudioClient and a simple in-memory IActivityTracker. No real LM Studio or SDK is touched — the manager file does not import the SDK dire
|
- `tests/lmStudioLifecycle.test.ts` (318 lines) — Unit tests for ModelLifecycleManager. Strategy: inject mock ILMStudioClient and a simple in-memory IActivityTracker. No real LM Studio or SDK is touched — the manager file does not import the SDK dire
|
||||||
- `tests/telegramBot.test.ts` (363 lines) — Unit tests for TelegramBot + truncateForTelegram. Strategy: - TelegramBot is driven by an injected ITelegramClient stub. We script getUpdates to return queued batches and assert that: - the offset cur
|
- `tests/telegramBot.test.ts` (363 lines) — Unit tests for TelegramBot + truncateForTelegram. Strategy: - TelegramBot is driven by an injected ITelegramClient stub. We script getUpdates to return queued batches and assert that: - the offset cur
|
||||||
- `tests/lmStudioStreamer.test.ts` (220 lines) — Unit tests for LMStudioStreamer. Strategy: inject a fake ILMStudioClient that returns a fake model handle whose respond() yields a controllable async iterable. No real SDK or WebSocket touched.
|
- `tests/lmStudioStreamer.test.ts` (220 lines) — Unit tests for LMStudioStreamer. Strategy: inject a fake ILMStudioClient that returns a fake model handle whose respond() yields a controllable async iterable. No real SDK or WebSocket touched.
|
||||||
@@ -160,10 +160,10 @@ flowchart LR
|
|||||||
- `core_py/optimizer.py` (55 lines)
|
- `core_py/optimizer.py` (55 lines)
|
||||||
- `core_py/queue_worker.py` (82 lines)
|
- `core_py/queue_worker.py` (82 lines)
|
||||||
|
|
||||||
### `docs/` — 60 files, ~2,545 lines
|
### `docs/` — 62 files, ~2,586 lines
|
||||||
|
|
||||||
**Sub-directories**
|
**Sub-directories**
|
||||||
- `docs/records/` (48) — Astra Project Chronicle Records
|
- `docs/records/` (50) — Astra Project Chronicle Records
|
||||||
- `docs/docs/` (5) — docs Chronicle Records
|
- `docs/docs/` (5) — docs Chronicle Records
|
||||||
|
|
||||||
**Key files**
|
**Key files**
|
||||||
@@ -172,7 +172,7 @@ flowchart LR
|
|||||||
- `docs/EXPERIENCE_MEMORY_PLAN.md` (122 lines) — Experience Memory (Mistake / Lesson Loop) — Implementation Plan
|
- `docs/EXPERIENCE_MEMORY_PLAN.md` (122 lines) — Experience Memory (Mistake / Lesson Loop) — Implementation Plan
|
||||||
- `docs/records/ConnectAI/development/2026-05-02_connectai_project_knowledge_overview.md` (121 lines) — Astra Project Knowledge Overview
|
- `docs/records/ConnectAI/development/2026-05-02_connectai_project_knowledge_overview.md` (121 lines) — Astra Project Knowledge Overview
|
||||||
- `docs/records/ConnectAI/development/2026-05-03_connectai_project_knowledge_overview.md` (121 lines) — Astra Project Knowledge Overview
|
- `docs/records/ConnectAI/development/2026-05-03_connectai_project_knowledge_overview.md` (121 lines) — Astra Project Knowledge Overview
|
||||||
- `docs/records/ConnectAI/timeline.md` (116 lines) — Project Timeline
|
- `docs/records/ConnectAI/timeline.md` (122 lines) — Project Timeline
|
||||||
- `docs/Advanced_Features_Implementation_Guide.md` (40 lines) — Advanced Features Implementation Guide
|
- `docs/Advanced_Features_Implementation_Guide.md` (40 lines) — Advanced Features Implementation Guide
|
||||||
- `docs/PROJECT_CHRONICLE_GUARD_ROADMAP.md` (43 lines) — Project Chronicle Guard: Search Engine Roadmap
|
- `docs/PROJECT_CHRONICLE_GUARD_ROADMAP.md` (43 lines) — Project Chronicle Guard: Search Engine Roadmap
|
||||||
- `docs/UX_UI_Consistency_Guidelines.md` (44 lines) — UX/UI Consistency Guidelines
|
- `docs/UX_UI_Consistency_Guidelines.md` (44 lines) — UX/UI Consistency Guidelines
|
||||||
@@ -196,7 +196,7 @@ flowchart LR
|
|||||||
## VS Code Extension Surface
|
## VS Code Extension Surface
|
||||||
- **Extension ID**: `g1nation.astra`
|
- **Extension ID**: `g1nation.astra`
|
||||||
- **Activation events**: `onStartupFinished`
|
- **Activation events**: `onStartupFinished`
|
||||||
- **Commands** (19):
|
- **Commands** (23):
|
||||||
- `g1nation.newChat` — Astra: New Chat
|
- `g1nation.newChat` — Astra: New Chat
|
||||||
- `g1nation.exportChat` — Astra: Export Chat as Markdown
|
- `g1nation.exportChat` — Astra: Export Chat as Markdown
|
||||||
- `g1nation.explainSelection` — Astra: Explain Selected Code
|
- `g1nation.explainSelection` — Astra: Explain Selected Code
|
||||||
@@ -215,8 +215,12 @@ flowchart LR
|
|||||||
- `g1nation.lesson.manage` — Astra: Browse / Manage Lessons
|
- `g1nation.lesson.manage` — Astra: Browse / Manage Lessons
|
||||||
- `g1nation.architecture.refresh` — Astra: Refresh Project Architecture Context
|
- `g1nation.architecture.refresh` — Astra: Refresh Project Architecture Context
|
||||||
- `g1nation.architecture.detach` — Astra: Detach Project Architecture Context
|
- `g1nation.architecture.detach` — Astra: Detach Project Architecture Context
|
||||||
|
- `g1nation.architecture.attach` — Astra: Attach Project Architecture Context
|
||||||
- `g1nation.architecture.open` — Astra: Open Project Architecture Doc
|
- `g1nation.architecture.open` — Astra: Open Project Architecture Doc
|
||||||
- **Configuration** (38 settings):
|
- `g1nation.company.toggle` — Astra: Toggle 1인 기업 Mode
|
||||||
|
- `g1nation.company.manage` — Astra: Manage 1인 기업 Agents
|
||||||
|
- `g1nation.company.openSessions` — Astra: Open 1인 기업 Sessions Folder
|
||||||
|
- **Configuration** (39 settings):
|
||||||
- `g1nation.multiAgentEnabled` *(boolean)* _(default: `false`)_ — Enable Multi-Agent Workflow (Planner -> Researcher -> Writer) for complex tasks.
|
- `g1nation.multiAgentEnabled` *(boolean)* _(default: `false`)_ — Enable Multi-Agent Workflow (Planner -> Researcher -> Writer) for complex tasks.
|
||||||
- `g1nation.memoryEnabled` *(boolean)* _(default: `true`)_ — Enable layered memory injection before each model response.
|
- `g1nation.memoryEnabled` *(boolean)* _(default: `true`)_ — Enable layered memory injection before each model response.
|
||||||
- `g1nation.memoryShortTermMessages` *(number)* _(default: `8`)_ — Number of recent conversation messages included as short-term memory.
|
- `g1nation.memoryShortTermMessages` *(number)* _(default: `8`)_ — Number of recent conversation messages included as short-term memory.
|
||||||
@@ -255,6 +259,7 @@ flowchart LR
|
|||||||
- `g1nation.embeddingModel` *(string)* _(default: `""`)_ — Embedding model registered in LM Studio / Ollama (e.g. 'text-embedding-bge-small-en-v1.5', 'nomic-embed-text', 'multilingual-e5-small'). When empty, Astra uses TF-IDF only. When set, the brain is embe
|
- `g1nation.embeddingModel` *(string)* _(default: `""`)_ — Embedding model registered in LM Studio / Ollama (e.g. 'text-embedding-bge-small-en-v1.5', 'nomic-embed-text', 'multilingual-e5-small'). When empty, Astra uses TF-IDF only. When set, the brain is embe
|
||||||
- `g1nation.embeddingBlendAlpha` *(number)* _(default: `0.5`)_ — Hybrid score blend: 0 = pure TF-IDF (sparse / keyword), 1 = pure embedding cosine (dense / semantic), 0.5 = balanced. Only used when g1nation.embeddingModel is set. Default 0.5.
|
- `g1nation.embeddingBlendAlpha` *(number)* _(default: `0.5`)_ — Hybrid score blend: 0 = pure TF-IDF (sparse / keyword), 1 = pure embedding cosine (dense / semantic), 0.5 = balanced. Only used when g1nation.embeddingModel is set. Default 0.5.
|
||||||
- `g1nation.knowledgeMix.secondBrainWeight` *(number)* _(default: `50`)_ — Knowledge Mix (0–100): how heavily the assistant should lean on Second Brain evidence vs. its own general knowledge. 0 = Second Brain disabled (model knowledge only). 50 = balanced (legacy default). 1
|
- `g1nation.knowledgeMix.secondBrainWeight` *(number)* _(default: `50`)_ — Knowledge Mix (0–100): how heavily the assistant should lean on Second Brain evidence vs. its own general knowledge. 0 = Second Brain disabled (model knowledge only). 50 = balanced (legacy default). 1
|
||||||
|
- `g1nation.enableReflection` *(boolean)* _(default: `true`)_ — Insert a Self-Reflection (Reflector) stage between Researcher and Writer in the multi-agent workflow. The Reflector critically reviews the plan and research output (gaps, contradictions, unsupported c
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
- **Runtime** (2): `@lmstudio/sdk`, `pdf-parse`
|
- **Runtime** (2): `@lmstudio/sdk`, `pdf-parse`
|
||||||
@@ -302,7 +307,7 @@ Astra는 대표님의 명시적인 승인 하에 로컬 시스템의 강력한
|
|||||||
**Designed for High-Performance Decision Making.**
|
**Designed for High-Performance Decision Making.**
|
||||||
Copyright (C) **g1nation**. All rights reserved.
|
Copyright (C) **g1nation**. All rights reserved.
|
||||||
|
|
||||||
_Last auto-scan: 2026-05-13T13:48:21.458Z · signature `fefc8c65`_
|
_Last auto-scan: 2026-05-13T16:44:14.023Z · signature `c63276ae`_
|
||||||
<!-- ASTRA:AUTO-END -->
|
<!-- ASTRA:AUTO-END -->
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"generatedAt": "2026-05-13T13:48:21.464Z",
|
"generatedAt": "2026-05-13T16:44:14.033Z",
|
||||||
"files": {
|
"files": {
|
||||||
"src/agent.ts": {
|
"src/agent.ts": {
|
||||||
"mtimeMs": 1778677012000,
|
"mtimeMs": 1778683690000,
|
||||||
"size": 184384,
|
"size": 185807,
|
||||||
"lines": 3207,
|
"lines": 3232,
|
||||||
"role": "",
|
"role": "",
|
||||||
"imports": [
|
"imports": [
|
||||||
"src/utils",
|
"src/utils",
|
||||||
@@ -38,19 +38,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/agents/AgentWorkflowManager.ts": {
|
"src/agents/AgentWorkflowManager.ts": {
|
||||||
"mtimeMs": 1777808065000,
|
"mtimeMs": 1778690404000,
|
||||||
"size": 1745,
|
"size": 2262,
|
||||||
"lines": 50,
|
"lines": 60,
|
||||||
"role": "",
|
"role": "",
|
||||||
"imports": [
|
"imports": [
|
||||||
"src/agents/factory",
|
"src/agents/factory",
|
||||||
"src/lib/engine"
|
"src/lib/engine",
|
||||||
|
"src/config"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/agents/factory.ts": {
|
"src/agents/factory.ts": {
|
||||||
"mtimeMs": 1778591282000,
|
"mtimeMs": 1778690336000,
|
||||||
"size": 7965,
|
"size": 11023,
|
||||||
"lines": 166,
|
"lines": 219,
|
||||||
"role": "",
|
"role": "",
|
||||||
"imports": [
|
"imports": [
|
||||||
"src/config",
|
"src/config",
|
||||||
@@ -58,7 +59,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/bridge.ts": {
|
"src/bridge.ts": {
|
||||||
"mtimeMs": 1778251262000,
|
"mtimeMs": 1778681774000,
|
||||||
"size": 9705,
|
"size": 9705,
|
||||||
"lines": 227,
|
"lines": 227,
|
||||||
"role": "",
|
"role": "",
|
||||||
@@ -71,9 +72,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/config.ts": {
|
"src/config.ts": {
|
||||||
"mtimeMs": 1778676053000,
|
"mtimeMs": 1778690442000,
|
||||||
"size": 9149,
|
"size": 9619,
|
||||||
"lines": 209,
|
"lines": 216,
|
||||||
"role": "",
|
"role": "",
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
@@ -248,9 +249,9 @@
|
|||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"src/extension.ts": {
|
"src/extension.ts": {
|
||||||
"mtimeMs": 1778677220000,
|
"mtimeMs": 1778687229000,
|
||||||
"size": 37920,
|
"size": 49361,
|
||||||
"lines": 757,
|
"lines": 945,
|
||||||
"role": "",
|
"role": "",
|
||||||
"imports": [
|
"imports": [
|
||||||
"src/utils",
|
"src/utils",
|
||||||
@@ -273,11 +274,13 @@
|
|||||||
"src/integrations/telegram/telegramClient",
|
"src/integrations/telegram/telegramClient",
|
||||||
"src/integrations/telegram/telegramBot",
|
"src/integrations/telegram/telegramBot",
|
||||||
"src/core/services",
|
"src/core/services",
|
||||||
|
"src/features/company",
|
||||||
"src/features/settings/settingsPanelProvider",
|
"src/features/settings/settingsPanelProvider",
|
||||||
"src/skills/agentKnowledgeMap",
|
"src/skills/agentKnowledgeMap",
|
||||||
"src/retrieval",
|
"src/retrieval",
|
||||||
"src/retrieval/lessonHelpers",
|
"src/retrieval/lessonHelpers",
|
||||||
"src/skills/scopedBrainRetriever"
|
"src/skills/scopedBrainRetriever",
|
||||||
|
"src/integrations/telegram/conversationHistory"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/features/approval/approvalPanelProvider.ts": {
|
"src/features/approval/approvalPanelProvider.ts": {
|
||||||
@@ -308,10 +311,160 @@
|
|||||||
"src/features/approval/approvalQueue"
|
"src/features/approval/approvalQueue"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"src/features/company/agents.ts": {
|
||||||
|
"mtimeMs": 1778680824000,
|
||||||
|
"size": 6684,
|
||||||
|
"lines": 136,
|
||||||
|
"role": "The 9-agent roster for 1인 기업 모드. Each entry is a static description — persona, role, specialty — used to build the specialist's system prompt at dispatch time. The set was adopted from Connectorigin's",
|
||||||
|
"imports": [
|
||||||
|
"src/features/company/types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"src/features/company/ceoPlanner.ts": {
|
||||||
|
"mtimeMs": 1778681095000,
|
||||||
|
"size": 8406,
|
||||||
|
"lines": 219,
|
||||||
|
"role": "CEO planner — turns a user prompt into a CompanyTaskPlan. Lifecycle of one planner call: 1. Build the planner system prompt (template + active-agent list). 2. Hit the AI service with the user prompt a",
|
||||||
|
"imports": [
|
||||||
|
"src/core/services",
|
||||||
|
"src/utils",
|
||||||
|
"src/features/company/agents",
|
||||||
|
"src/features/company/companyConfig",
|
||||||
|
"src/features/company/promptAssets",
|
||||||
|
"src/features/company/promptBuilder",
|
||||||
|
"src/features/company/types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"src/features/company/ceoReporter.ts": {
|
||||||
|
"mtimeMs": 1778681122000,
|
||||||
|
"size": 4812,
|
||||||
|
"lines": 120,
|
||||||
|
"role": "CEO synthesis pass — runs after all specialists have finished. Given the per-agent outputs, this asks the CEO model to produce the final markdown report (✅ 완료 / 🚀 다음 / 💡 인사이트) that the user actually",
|
||||||
|
"imports": [
|
||||||
|
"src/core/services",
|
||||||
|
"src/utils",
|
||||||
|
"src/features/company/agents",
|
||||||
|
"src/features/company/promptAssets",
|
||||||
|
"src/features/company/types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"src/features/company/companyConfig.ts": {
|
||||||
|
"mtimeMs": 1778686762000,
|
||||||
|
"size": 13473,
|
||||||
|
"lines": 330,
|
||||||
|
"role": "State + config plumbing for 1인 기업 모드. Two surfaces: - CompanyState (runtime data: enabled flag, company name, which agents are active, per-agent model overrides). Persisted in VS Code's globalState so",
|
||||||
|
"imports": [
|
||||||
|
"src/features/company/agents",
|
||||||
|
"src/features/company/types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"src/features/company/dispatcher.ts": {
|
||||||
|
"mtimeMs": 1778686839000,
|
||||||
|
"size": 20029,
|
||||||
|
"lines": 434,
|
||||||
|
"role": "Sequential dispatcher for 1인 기업 모드. Drives one company \"turn\": user prompt → CEO planner (JSON {brief, tasks}) → for each task in plan: dispatch one specialist (sequentially) - build specialist prompt",
|
||||||
|
"imports": [
|
||||||
|
"src/core/services",
|
||||||
|
"src/utils",
|
||||||
|
"src/skills/scopedBrainRetriever",
|
||||||
|
"src/skills/agentKnowledgeMap",
|
||||||
|
"src/retrieval/knowledgeMix",
|
||||||
|
"src/features/company/agents",
|
||||||
|
"src/features/company/companyConfig",
|
||||||
|
"src/features/company/ceoPlanner",
|
||||||
|
"src/features/company/ceoReporter",
|
||||||
|
"src/features/company/promptBuilder",
|
||||||
|
"src/features/company/sessionStore",
|
||||||
|
"src/features/company/telegramReport",
|
||||||
|
"src/features/company/types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"src/features/company/index.ts": {
|
||||||
|
"mtimeMs": 1778686769000,
|
||||||
|
"size": 1114,
|
||||||
|
"lines": 55,
|
||||||
|
"role": "Public API for 1인 기업 모드. Consumers (sidebarProvider, chatHandlers, command handlers) import from this barrel so internal layout can move around without touching every call site.",
|
||||||
|
"imports": [
|
||||||
|
"src/features/company/agents",
|
||||||
|
"src/features/company/companyConfig",
|
||||||
|
"src/features/company/types",
|
||||||
|
"src/features/company/dispatcher",
|
||||||
|
"src/features/company/sessionStore"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"src/features/company/promptAssets.ts": {
|
||||||
|
"mtimeMs": 1778680887000,
|
||||||
|
"size": 6782,
|
||||||
|
"lines": 114,
|
||||||
|
"role": "Inlined prompt assets for the 1인 기업 mode. The CEO planner / reporter / casual-chat prompts are kept as TS string constants rather than loaded from prompts/.md at runtime, for two reasons: 1. Bundling.",
|
||||||
|
"imports": []
|
||||||
|
},
|
||||||
|
"src/features/company/promptBuilder.ts": {
|
||||||
|
"mtimeMs": 1778686868000,
|
||||||
|
"size": 10317,
|
||||||
|
"lines": 202,
|
||||||
|
"role": "System-prompt construction for company-mode agents. Each specialist needs a prompt that includes: - Their identity (name, role, specialty) + optional persona. - The action-tag contract (<createfile>, ",
|
||||||
|
"imports": [
|
||||||
|
"src/features/company/agents",
|
||||||
|
"src/features/company/companyConfig",
|
||||||
|
"src/features/company/types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"src/features/company/prompts/ceo-chat.md": {
|
||||||
|
"mtimeMs": 1778680831000,
|
||||||
|
"size": 462,
|
||||||
|
"lines": 4,
|
||||||
|
"role": "당신은 {{COMPANY}}의 CEO입니다. 사용자(사장님)와 짧게 인사·안부·잡담을 주고받습니다. - 한국어로 1~3문장. 친근하지만 사장-CEO 관계는 유지. - 인사·안부 질문이면 자연스럽게 응답하세요. 작업 지시가 아니면 굳이 작업 분배 제안 X. - 회사 정체성·최근 결정·추적기 상태가 컨텍스트에 있으면 자연스럽게 활용. - JSON 출력 금지. ",
|
||||||
|
"imports": []
|
||||||
|
},
|
||||||
|
"src/features/company/prompts/ceo-planner.md": {
|
||||||
|
"mtimeMs": 1778680831000,
|
||||||
|
"size": 3199,
|
||||||
|
"lines": 38,
|
||||||
|
"role": "당신은 \"{{COMPANY}}\"의 CEO입니다. 1인 AI 기업의 사령관이자 오케스트레이터입니다.",
|
||||||
|
"imports": []
|
||||||
|
},
|
||||||
|
"src/features/company/prompts/ceo-report.md": {
|
||||||
|
"mtimeMs": 1778680831000,
|
||||||
|
"size": 1373,
|
||||||
|
"lines": 21,
|
||||||
|
"role": "당신은 {{COMPANY}}의 CEO입니다. 방금 팀이 작업을 끝냈습니다. 각 에이전트의 산출물을 읽고 사장님께 올릴 종합 보고서를 작성하세요.",
|
||||||
|
"imports": []
|
||||||
|
},
|
||||||
|
"src/features/company/sessionStore.ts": {
|
||||||
|
"mtimeMs": 1778680971000,
|
||||||
|
"size": 8727,
|
||||||
|
"lines": 231,
|
||||||
|
"role": "Disk persistence for company-mode session artefacts. Each company turn produces a timestamped directory: <workspaceRoot>/.astra/company/sessions/2026-05-13T21-29/ ├─ brief.md ← CEO's task decompositio",
|
||||||
|
"imports": [
|
||||||
|
"src/utils",
|
||||||
|
"src/features/company/types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"src/features/company/telegramReport.ts": {
|
||||||
|
"mtimeMs": 1778686162000,
|
||||||
|
"size": 8111,
|
||||||
|
"lines": 168,
|
||||||
|
"role": "Telegram mirror for the secretary agent (영숙). After every company turn finishes, this helper takes the CEO synthesis + task list and pushes it to the user's Telegram chat — same behaviour as Connector",
|
||||||
|
"imports": [
|
||||||
|
"src/utils",
|
||||||
|
"src/integrations/telegram/telegramClient",
|
||||||
|
"src/integrations/telegram/conversationHistory",
|
||||||
|
"src/features/company/agents",
|
||||||
|
"src/features/company/types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"src/features/company/types.ts": {
|
||||||
|
"mtimeMs": 1778686714000,
|
||||||
|
"size": 6454,
|
||||||
|
"lines": 150,
|
||||||
|
"role": "Type definitions for the 1인 기업 (One-Person Company) mode. The mode turns the user into a virtual CEO that dispatches work to a roster of specialist agents. Each turn produces a session directory conta",
|
||||||
|
"imports": []
|
||||||
|
},
|
||||||
"src/features/projectArchitecture/index.ts": {
|
"src/features/projectArchitecture/index.ts": {
|
||||||
"mtimeMs": 1778679015000,
|
"mtimeMs": 1778684164000,
|
||||||
"size": 22657,
|
"size": 23147,
|
||||||
"lines": 515,
|
"lines": 523,
|
||||||
"role": "Project Architecture Context (Feature 2) Builds a markdown document that captures the durable facts about a project — its purpose, modules, key files, constraints, decisions — so Astra can attach it t",
|
"role": "Project Architecture Context (Feature 2) Builds a markdown document that captures the durable facts about a project — its purpose, modules, key files, constraints, decisions — so Astra can attach it t",
|
||||||
"imports": [
|
"imports": [
|
||||||
"src/utils",
|
"src/utils",
|
||||||
@@ -413,6 +566,15 @@
|
|||||||
"src/lib/paths"
|
"src/lib/paths"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"src/integrations/telegram/conversationHistory.ts": {
|
||||||
|
"mtimeMs": 1778684811000,
|
||||||
|
"size": 6273,
|
||||||
|
"lines": 154,
|
||||||
|
"role": "Per-chat conversation history for the Telegram bot. Why this exists: the previous bot was stateless — every inbound message hit AIService.chat({system, user}) in isolation, with no memory of what the ",
|
||||||
|
"imports": [
|
||||||
|
"src/utils"
|
||||||
|
]
|
||||||
|
},
|
||||||
"src/integrations/telegram/telegramBot.ts": {
|
"src/integrations/telegram/telegramBot.ts": {
|
||||||
"mtimeMs": 1778421270000,
|
"mtimeMs": 1778421270000,
|
||||||
"size": 11344,
|
"size": 11344,
|
||||||
@@ -467,9 +629,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/lib/engine.ts": {
|
"src/lib/engine.ts": {
|
||||||
"mtimeMs": 1777985699000,
|
"mtimeMs": 1778690608000,
|
||||||
"size": 38497,
|
"size": 40830,
|
||||||
"lines": 849,
|
"lines": 880,
|
||||||
"role": "",
|
"role": "",
|
||||||
"imports": [
|
"imports": [
|
||||||
"src/core/lock",
|
"src/core/lock",
|
||||||
@@ -740,14 +902,15 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/sidebar/chatHandlers.ts": {
|
"src/sidebar/chatHandlers.ts": {
|
||||||
"mtimeMs": 1778677129000,
|
"mtimeMs": 1778686906000,
|
||||||
"size": 8596,
|
"size": 13454,
|
||||||
"lines": 175,
|
"lines": 266,
|
||||||
"role": "",
|
"role": "",
|
||||||
"imports": [
|
"imports": [
|
||||||
"src/sidebarProvider",
|
"src/sidebarProvider",
|
||||||
"src/utils",
|
"src/utils",
|
||||||
"src/lib/paths"
|
"src/lib/paths",
|
||||||
|
"src/features/company"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/sidebar/chronicleHandlers.ts": {
|
"src/sidebar/chronicleHandlers.ts": {
|
||||||
@@ -760,9 +923,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/sidebarProvider.ts": {
|
"src/sidebarProvider.ts": {
|
||||||
"mtimeMs": 1778679027000,
|
"mtimeMs": 1778686896000,
|
||||||
"size": 112397,
|
"size": 127185,
|
||||||
"lines": 2603,
|
"lines": 2934,
|
||||||
"role": "",
|
"role": "",
|
||||||
"imports": [
|
"imports": [
|
||||||
"src/utils",
|
"src/utils",
|
||||||
@@ -780,7 +943,9 @@
|
|||||||
"src/lib/contextManager",
|
"src/lib/contextManager",
|
||||||
"src/skills/externalSkillLoader",
|
"src/skills/externalSkillLoader",
|
||||||
"src/features/projectArchitecture",
|
"src/features/projectArchitecture",
|
||||||
"src/features/projectArchitecture/intentDetector"
|
"src/features/projectArchitecture/intentDetector",
|
||||||
|
"src/features/company",
|
||||||
|
"src/core/services"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/skills/agentKnowledgeMap.ts": {
|
"src/skills/agentKnowledgeMap.ts": {
|
||||||
@@ -816,7 +981,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/skills/skillInjectionService.ts": {
|
"src/skills/skillInjectionService.ts": {
|
||||||
"mtimeMs": 1778251221000,
|
"mtimeMs": 1778681774000,
|
||||||
"size": 6276,
|
"size": 6276,
|
||||||
"lines": 145,
|
"lines": 145,
|
||||||
"role": "",
|
"role": "",
|
||||||
@@ -870,30 +1035,30 @@
|
|||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"media/sidebar.css": {
|
"media/sidebar.css": {
|
||||||
"mtimeMs": 1778677793000,
|
"mtimeMs": 1778688155000,
|
||||||
"size": 38372,
|
"size": 49347,
|
||||||
"lines": 987,
|
"lines": 1225,
|
||||||
"role": "Stylesheet",
|
"role": "Stylesheet",
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"media/sidebar.html": {
|
"media/sidebar.html": {
|
||||||
"mtimeMs": 1778677855000,
|
"mtimeMs": 1778687548000,
|
||||||
"size": 16364,
|
"size": 20499,
|
||||||
"lines": 285,
|
"lines": 356,
|
||||||
"role": "Astra",
|
"role": "Astra",
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"media/sidebar.js": {
|
"media/sidebar.js": {
|
||||||
"mtimeMs": 1778677844000,
|
"mtimeMs": 1778688191000,
|
||||||
"size": 77309,
|
"size": 103898,
|
||||||
"lines": 1388,
|
"lines": 1874,
|
||||||
"role": "",
|
"role": "",
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"tests/agentEngine.test.ts": {
|
"tests/agentEngine.test.ts": {
|
||||||
"mtimeMs": 1777983087000,
|
"mtimeMs": 1778690526000,
|
||||||
"size": 27182,
|
"size": 33414,
|
||||||
"lines": 646,
|
"lines": 776,
|
||||||
"role": "AgentEngine Integration Tests & Performance Benchmarks 검증 대상: 1. ErrorClassifier — 오류 유형(Transient/Permanent/Abort) 자동 분류 2. ErrorRecoveryMatrix — 각 규칙이 의도한 대응 전략으로 매핑되는지 검증 3. resilientExecute — 지수 백",
|
"role": "AgentEngine Integration Tests & Performance Benchmarks 검증 대상: 1. ErrorClassifier — 오류 유형(Transient/Permanent/Abort) 자동 분류 2. ErrorRecoveryMatrix — 각 규칙이 의도한 대응 전략으로 매핑되는지 검증 3. resilientExecute — 지수 백",
|
||||||
"imports": [
|
"imports": [
|
||||||
"src/lib/engine"
|
"src/lib/engine"
|
||||||
@@ -1083,7 +1248,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"tests/skillInjectionService.test.ts": {
|
"tests/skillInjectionService.test.ts": {
|
||||||
"mtimeMs": 1778251292000,
|
"mtimeMs": 1778681774000,
|
||||||
"size": 6741,
|
"size": 6741,
|
||||||
"lines": 172,
|
"lines": 172,
|
||||||
"role": "Unit tests for FileSystemSkillInjectionService. Strategy: drive the service against a real temp directory so path-traversal defenses and writeFileSync paths are exercised end-to-end. The service accep",
|
"role": "Unit tests for FileSystemSkillInjectionService. Strategy: drive the service against a real temp directory so path-traversal defenses and writeFileSync paths are exercised end-to-end. The service accep",
|
||||||
@@ -1343,7 +1508,7 @@
|
|||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"docs/records/ConnectAI/chronicle.config.json": {
|
"docs/records/ConnectAI/chronicle.config.json": {
|
||||||
"mtimeMs": 1778680095000,
|
"mtimeMs": 1778690568000,
|
||||||
"size": 416,
|
"size": 416,
|
||||||
"lines": 11,
|
"lines": 11,
|
||||||
"role": "JSON configuration",
|
"role": "JSON configuration",
|
||||||
@@ -1412,6 +1577,13 @@
|
|||||||
"role": "ADR: 이 프로젝트의 구조에 대해서 설명해봐.",
|
"role": "ADR: 이 프로젝트의 구조에 대해서 설명해봐.",
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
|
"docs/records/ConnectAI/decisions/ADR-0010-volumes-data-project-antigravity-connectai-self-reflection-기.md": {
|
||||||
|
"mtimeMs": 1778689955000,
|
||||||
|
"size": 1468,
|
||||||
|
"lines": 19,
|
||||||
|
"role": "ADR: /Volumes/Data/project/Antigravity/ConnectAI self reflection 기능이 적용되었는지 확인해줘. 1인 ...",
|
||||||
|
"imports": []
|
||||||
|
},
|
||||||
"docs/records/ConnectAI/development/2026-05-02_answer-format-readability-tuning.md": {
|
"docs/records/ConnectAI/development/2026-05-02_answer-format-readability-tuning.md": {
|
||||||
"mtimeMs": 1777808065000,
|
"mtimeMs": 1777808065000,
|
||||||
"size": 1534,
|
"size": 1534,
|
||||||
@@ -1552,6 +1724,13 @@
|
|||||||
"role": "Discussion: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 작업할거야",
|
"role": "Discussion: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 작업할거야",
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
|
"docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-하위-폴더-포함해서.md": {
|
||||||
|
"mtimeMs": 1778689036000,
|
||||||
|
"size": 720,
|
||||||
|
"lines": 16,
|
||||||
|
"role": "Discussion: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 하위 폴더 포함해서 딥 리서치 해줘. 최적화 할 부분...",
|
||||||
|
"imports": []
|
||||||
|
},
|
||||||
"docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트를-작업할거야.md": {
|
"docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트를-작업할거야.md": {
|
||||||
"mtimeMs": 1778677791000,
|
"mtimeMs": 1778677791000,
|
||||||
"size": 719,
|
"size": 719,
|
||||||
@@ -1588,9 +1767,9 @@
|
|||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"docs/records/ConnectAI/timeline.md": {
|
"docs/records/ConnectAI/timeline.md": {
|
||||||
"mtimeMs": 1778680095000,
|
"mtimeMs": 1778689955000,
|
||||||
"size": 7871,
|
"size": 8165,
|
||||||
"lines": 116,
|
"lines": 122,
|
||||||
"role": "Project Timeline",
|
"role": "Project Timeline",
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"result": "Final report with inconsistencies. This should be long enough to pass validation.",
|
"result": "Final report with inconsistencies. This should be long enough to pass validation.",
|
||||||
"createdAt": 1778688441641,
|
"createdAt": 1778690820030,
|
||||||
"modelVersion": "unknown"
|
"modelVersion": "unknown"
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"result": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
|
"result": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
|
||||||
"createdAt": 1778688441640,
|
"createdAt": 1778690820030,
|
||||||
"modelVersion": "unknown"
|
"modelVersion": "unknown"
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"result": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
|
"result": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
|
||||||
"createdAt": 1778688441639,
|
"createdAt": 1778690820029,
|
||||||
"modelVersion": "unknown"
|
"modelVersion": "unknown"
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"result": "---\nid: stress_conflict_1778688441629\ndate: 2026-05-13T16:07:21.641Z\ntype: knowledge_artifact\nstandard: P-Reinforce v3.0\ntags: [automated, connect_ai, brain_sync]\n---\n\n## 📌 Brief Summary\nFinal report with inconsistencies. This should be long enough to pass validation.\n\nFinal report with inconsistencies. This should be long enough to pass validation.\n\n---\n## 💡 Astra의 선제적 제안 (Proactive Next Actions)\nFinal report with inconsistencies. This should be long enough to pass validation.\n---\n## 🛡️ Reliability & Audit Summary\n> [!NOTE]\n> 이 문서는 ConnectAI의 **Intelligent Resilience** 엔진에 의해 검증 및 정제되었습니다.\n\n| Metric | Value | Status |\n| :--- | :--- | :--- |\n| **Conflict Risk** | `60/100` | ⚠️ Medium |\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- **[PLANNER]** 전략 수립 중... (10ms)\n- **[RESEARCHER]** 핵심 정보 수집 및 분석 중... (1ms)\n- **[WRITER]** 최종 리포트 작성 및 편집 중... (0ms)\n",
|
"result": "---\nid: stress_conflict_1778690820018\ndate: 2026-05-13T16:47:00.031Z\ntype: knowledge_artifact\nstandard: P-Reinforce v3.0\ntags: [automated, connect_ai, brain_sync]\n---\n\n## 📌 Brief Summary\nFinal report with inconsistencies. This should be long enough to pass validation.\n\nFinal report with inconsistencies. This should be long enough to pass validation.\n\n---\n## 💡 Astra의 선제적 제안 (Proactive Next Actions)\nFinal report with inconsistencies. This should be long enough to pass validation.\n---\n## 🛡️ Reliability & Audit Summary\n> [!NOTE]\n> 이 문서는 ConnectAI의 **Intelligent Resilience** 엔진에 의해 검증 및 정제되었습니다.\n\n| Metric | Value | Status |\n| :--- | :--- | :--- |\n| **Conflict Risk** | `60/100` | ⚠️ Medium |\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- **[PLANNER]** 전략 수립 중... (11ms)\n- **[RESEARCHER]** 핵심 정보 수집 및 분석 중... (0ms)\n- **[WRITER]** 최종 리포트 작성 및 편집 중... (1ms)\n",
|
||||||
"createdAt": 1778688441641,
|
"createdAt": 1778690820031,
|
||||||
"modelVersion": "unknown"
|
"modelVersion": "unknown"
|
||||||
}
|
}
|
||||||
+10
-10
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"missionId": "stress_conflict_1778688441629",
|
"missionId": "stress_conflict_1778690820018",
|
||||||
"status": "completed",
|
"status": "completed",
|
||||||
"startTime": "2026-05-13T16:07:21.629Z",
|
"startTime": "2026-05-13T16:47:00.018Z",
|
||||||
"totalElapsedMs": 12,
|
"totalElapsedMs": 13,
|
||||||
"results": {
|
"results": {
|
||||||
"planner": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
|
"planner": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
|
||||||
"researcher": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
|
"researcher": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
|
||||||
@@ -16,30 +16,30 @@
|
|||||||
{
|
{
|
||||||
"from": "idle",
|
"from": "idle",
|
||||||
"to": "planner",
|
"to": "planner",
|
||||||
"durationMs": 10,
|
"durationMs": 11,
|
||||||
"message": "전략 수립 중...",
|
"message": "전략 수립 중...",
|
||||||
"ts": "2026-05-13T16:07:21.639Z"
|
"ts": "2026-05-13T16:47:00.029Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "planner",
|
"from": "planner",
|
||||||
"to": "researcher",
|
"to": "researcher",
|
||||||
"durationMs": 1,
|
"durationMs": 0,
|
||||||
"message": "핵심 정보 수집 및 분석 중...",
|
"message": "핵심 정보 수집 및 분석 중...",
|
||||||
"ts": "2026-05-13T16:07:21.640Z"
|
"ts": "2026-05-13T16:47:00.029Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "researcher",
|
"from": "researcher",
|
||||||
"to": "writer",
|
"to": "writer",
|
||||||
"durationMs": 0,
|
"durationMs": 1,
|
||||||
"message": "최종 리포트 작성 및 편집 중...",
|
"message": "최종 리포트 작성 및 편집 중...",
|
||||||
"ts": "2026-05-13T16:07:21.640Z"
|
"ts": "2026-05-13T16:47:00.030Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "writer",
|
"from": "writer",
|
||||||
"to": "completed",
|
"to": "completed",
|
||||||
"durationMs": 1,
|
"durationMs": 1,
|
||||||
"message": "미션 완료",
|
"message": "미션 완료",
|
||||||
"ts": "2026-05-13T16:07:21.641Z"
|
"ts": "2026-05-13T16:47:00.031Z"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"resilienceMetrics": {
|
"resilienceMetrics": {
|
||||||
@@ -7,5 +7,5 @@
|
|||||||
"corePurpose": "",
|
"corePurpose": "",
|
||||||
"detailLevel": "standard",
|
"detailLevel": "standard",
|
||||||
"createdAt": "2026-05-13T13:09:33.788Z",
|
"createdAt": "2026-05-13T13:09:33.788Z",
|
||||||
"updatedAt": "2026-05-13T13:48:15.283Z"
|
"updatedAt": "2026-05-13T16:44:33.835Z"
|
||||||
}
|
}
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
# ADR: /Volumes/Data/project/Antigravity/ConnectAI self reflection 기능이 적용되었는지 확인해줘. 1인 ...
|
||||||
|
|
||||||
|
## Status
|
||||||
|
accepted
|
||||||
|
|
||||||
|
## Context
|
||||||
|
/Volumes/Data/project/Antigravity/ConnectAI self reflection 기능이 적용되었는지 확인해줘. 1인 기업 기능에.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
확인했습니다. 현재 제공된 프로젝트 기록과 아키텍처 문서를 바탕으로 `/Volumes/Data/project/Antigravity/ConnectAI` 내의 '자체 성찰(Self-Reflection)' 기능 적용 여부를 분석하겠습니다. **결론부터 말씀드리자면, 시스템 설계 상으로는 자체 성찰 및 피드백 루프를 위한 강력한 기반이 구축되어 있습니다.** 하지만 실제 실행 환경에서 이 기능이 완벽하게 작동하고 있는지에 대한 **실행 결과(Execution Trace)**는 별도로 확인해야 합니다. ### 상세 분석 1. **아키텍처적 기반 (Foundation):** * `AgentEngine Architecture Document`에 따르면, 시스템은 Planner → Researcher → Writer의 3단계 멀티 에이전트 워크플로우를 통해 요청을 분할 처리합니다. 이는 단순 실행을 넘어 **메타인지(Meta-cognition)**와 **결과 검증** 단계가 필요함을 내포하고 있습...
|
||||||
|
|
||||||
|
## Reason
|
||||||
|
Captured automatically because the conversation contained decision-oriented language.
|
||||||
|
|
||||||
|
## Alternatives
|
||||||
|
Not captured yet.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
- Future prompts should treat this as project context unless the user changes direction.
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
# Discussion: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 작업 할 거야.
|
||||||
|
|
||||||
|
## User Request Summary
|
||||||
|
/Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 작업 할 거야.
|
||||||
|
|
||||||
|
## Interpreted Intent
|
||||||
|
Capture a meaningful project discussion automatically instead of requiring manual record selection.
|
||||||
|
|
||||||
|
## Questions
|
||||||
|
No explicit question was captured.
|
||||||
|
|
||||||
|
## Main Discussion
|
||||||
|
- 프로젝트를 시작하시려는군요. 해당 경로를 기준으로 작업을 진행하겠습니다. 어떤 부분부터 논의하거나 어떤 목표를 가지고 시작하고 싶으신지 말씀해 주십시오.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
No decisions captured yet.
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
# Discussion: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 하위 폴더 포함해서 딥 리서치 해줘. 최적화 할 부분...
|
||||||
|
|
||||||
|
## User Request Summary
|
||||||
|
/Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 하위 폴더 포함해서 딥 리서치 해줘. 최적화 할 부분이 뭐가 더 있을지.
|
||||||
|
|
||||||
|
## Interpreted Intent
|
||||||
|
Capture a meaningful project discussion automatically instead of requiring manual record selection.
|
||||||
|
|
||||||
|
## Questions
|
||||||
|
No explicit question was captured.
|
||||||
|
|
||||||
|
## Main Discussion
|
||||||
|
- /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 하위 폴더 포함해서 딥 리서치 해줘. 최적화 할 부분이 뭐가 더 있을지.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
No decisions captured yet.
|
||||||
@@ -114,3 +114,12 @@
|
|||||||
|
|
||||||
## 2026-05-13
|
## 2026-05-13
|
||||||
- Auto discussion record created: discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업할거야.md
|
- Auto discussion record created: discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업할거야.md
|
||||||
|
|
||||||
|
## 2026-05-13
|
||||||
|
- Auto discussion record created: discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-하위-폴더-포함해서.md
|
||||||
|
|
||||||
|
## 2026-05-13
|
||||||
|
- Auto decision record created: decisions/ADR-0010-volumes-data-project-antigravity-connectai-self-reflection-기.md
|
||||||
|
|
||||||
|
## 2026-05-13
|
||||||
|
- Auto discussion record created: discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업-할-거야.md
|
||||||
|
|||||||
@@ -411,6 +411,11 @@
|
|||||||
"minimum": 0,
|
"minimum": 0,
|
||||||
"maximum": 100,
|
"maximum": 100,
|
||||||
"description": "Knowledge Mix (0–100): how heavily the assistant should lean on Second Brain evidence vs. its own general knowledge. 0 = Second Brain disabled (model knowledge only). 50 = balanced (legacy default). 100 = Second Brain is the primary evidence; model knowledge only fills harmless background. Per-agent overrides in the Agent Mapping panel win over this global value."
|
"description": "Knowledge Mix (0–100): how heavily the assistant should lean on Second Brain evidence vs. its own general knowledge. 0 = Second Brain disabled (model knowledge only). 50 = balanced (legacy default). 100 = Second Brain is the primary evidence; model knowledge only fills harmless background. Per-agent overrides in the Agent Mapping panel win over this global value."
|
||||||
|
},
|
||||||
|
"g1nation.enableReflection": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Insert a Self-Reflection (Reflector) stage between Researcher and Writer in the multi-agent workflow. The Reflector critically reviews the plan and research output (gaps, contradictions, unsupported claims, drift from the original objective) and feeds a structured critique to the Writer, which must address it before producing the final report. Reflection failures are non-fatal (the Writer still runs with empty critique). Disable to save one LLM call per mission if you prioritize latency or are running on a very small model."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { PlannerAgent, ResearcherAgent, WriterAgent } from './factory';
|
import { PlannerAgent, ResearcherAgent, ReflectorAgent, WriterAgent } from './factory';
|
||||||
import { AgentEngine, PipelineStage } from '../lib/engine';
|
import { AgentEngine, PipelineStage, AgentExecuteOptions } from '../lib/engine';
|
||||||
|
import { getConfig } from '../config';
|
||||||
|
|
||||||
export class AgentWorkflowManager {
|
export class AgentWorkflowManager {
|
||||||
/**
|
/**
|
||||||
@@ -15,9 +16,16 @@ export class AgentWorkflowManager {
|
|||||||
const planner = new PlannerAgent(modelName);
|
const planner = new PlannerAgent(modelName);
|
||||||
const researcher = new ResearcherAgent(modelName);
|
const researcher = new ResearcherAgent(modelName);
|
||||||
const writer = new WriterAgent(modelName);
|
const writer = new WriterAgent(modelName);
|
||||||
const engine = new AgentEngine(planner, researcher, writer);
|
// [Self-Reflection] 설정으로 비활성화하지 않은 경우에만 Reflector를 주입.
|
||||||
|
const enableReflection = getConfig().enableReflection !== false;
|
||||||
|
const reflector = enableReflection ? new ReflectorAgent(modelName) : undefined;
|
||||||
|
const engine = new AgentEngine(planner, researcher, writer, reflector);
|
||||||
const missionId = `mission_${Date.now()}`;
|
const missionId = `mission_${Date.now()}`;
|
||||||
|
|
||||||
|
const runOptions: AgentExecuteOptions = {
|
||||||
|
config: { enableReflection }
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await engine.runMission(
|
return await engine.runMission(
|
||||||
missionId,
|
missionId,
|
||||||
@@ -26,7 +34,8 @@ export class AgentWorkflowManager {
|
|||||||
signal,
|
signal,
|
||||||
(stage: PipelineStage, message: string) => {
|
(stage: PipelineStage, message: string) => {
|
||||||
onProgress(this.mapStageToUI(stage), message);
|
onProgress(this.mapStageToUI(stage), message);
|
||||||
}
|
},
|
||||||
|
runOptions
|
||||||
);
|
);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error.name === 'AbortError' || error.message.includes('cancelled')) {
|
if (error.name === 'AbortError' || error.message.includes('cancelled')) {
|
||||||
@@ -41,6 +50,7 @@ export class AgentWorkflowManager {
|
|||||||
idle: '대기',
|
idle: '대기',
|
||||||
planner: 'Planner',
|
planner: 'Planner',
|
||||||
researcher: 'Researcher',
|
researcher: 'Researcher',
|
||||||
|
reflector: 'Reflector',
|
||||||
writer: 'Writer',
|
writer: 'Writer',
|
||||||
completed: '완료',
|
completed: '완료',
|
||||||
error: '오류'
|
error: '오류'
|
||||||
|
|||||||
+55
-2
@@ -139,7 +139,8 @@ Your goal is to produce a state-of-the-art final report that wows the user.
|
|||||||
- TONE: Authoritative yet accessible. Professional developer/consultant style.
|
- TONE: Authoritative yet accessible. Professional developer/consultant style.
|
||||||
- STRUCTURE: Use an executive summary, detailed analysis sections, and a "Final Recommendation" block.
|
- STRUCTURE: Use an executive summary, detailed analysis sections, and a "Final Recommendation" block.
|
||||||
- LANGUAGE: Always respond in the user's language (KOREAN).
|
- LANGUAGE: Always respond in the user's language (KOREAN).
|
||||||
- POLISHING: Ensure logical flow between sections. Make it look like a premium report.`;
|
- POLISHING: Ensure logical flow between sections. Make it look like a premium report.
|
||||||
|
- SELF-CORRECTION: When a [REFLECTION CRITIQUE] block is provided, you MUST address each listed gap, contradiction, or missing-evidence item explicitly before producing the final report. Do not silently ignore the critique.`;
|
||||||
|
|
||||||
async execute(input: string, originalRequest?: string, signal?: AbortSignal, options?: AgentExecuteOptions): Promise<string> {
|
async execute(input: string, originalRequest?: string, signal?: AbortSignal, options?: AgentExecuteOptions): Promise<string> {
|
||||||
// [Astra v4.0] Advisor 모드 처리
|
// [Astra v4.0] Advisor 모드 처리
|
||||||
@@ -156,11 +157,63 @@ Analyze the provided report and suggest 3 high-impact next actions for the user.
|
|||||||
const trimmedData = input.length > 8000 ? input.substring(0, 8000) + '... [Data Trimmed for Performance]' : input;
|
const trimmedData = input.length > 8000 ? input.substring(0, 8000) + '... [Data Trimmed for Performance]' : input;
|
||||||
|
|
||||||
const policy = options?.context || '';
|
const policy = options?.context || '';
|
||||||
|
const reflection = options?.priorResults?.reflection;
|
||||||
|
// Reflector 결과가 있으면 별도 블록으로 주입. 길이 4000자 cap (Writer 입력 비대화 방지).
|
||||||
|
const reflectionBlock = reflection && reflection.trim().length > 0
|
||||||
|
? `\n5. [REFLECTION CRITIQUE — must be addressed]:\n${reflection.length > 4000 ? reflection.substring(0, 4000) + '... [Critique Trimmed]' : reflection}`
|
||||||
|
: '';
|
||||||
|
|
||||||
const wrappedInput = `### SYSTEM INSTRUCTION: FINAL SYNTHESIS
|
const wrappedInput = `### SYSTEM INSTRUCTION: FINAL SYNTHESIS
|
||||||
1. Gathered Research Data: ${trimmedData}
|
1. Gathered Research Data: ${trimmedData}
|
||||||
2. User's Original Objective: ${originalRequest}
|
2. User's Original Objective: ${originalRequest}
|
||||||
3. Applied Knowledge & Filtering Policy: ${policy}
|
3. Applied Knowledge & Filtering Policy: ${policy}
|
||||||
4. Mission: Write the definitive final report in KOREAN.`;
|
4. Mission: Write the definitive final report in KOREAN.${reflectionBlock}`;
|
||||||
|
return this.callLLM(this.persona, wrappedInput, signal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ReflectorAgent extends BaseAgent {
|
||||||
|
private readonly persona = `You are the [Internal Critic & Self-Reflection Officer].
|
||||||
|
Your sole role is META-COGNITION: stress-test the plan and the research output BEFORE the Writer commits to a final report.
|
||||||
|
- POSTURE: Skeptical, rigorous, blunt. You are looking for what is WRONG, not what is right.
|
||||||
|
- DO NOT: rewrite the report, add new content, or speculate beyond the evidence provided.
|
||||||
|
- DO: surface gaps, unsupported claims, contradictions, drift from the original objective, and missing perspectives.
|
||||||
|
- OUTPUT STRICTLY in this Markdown shape (Korean):
|
||||||
|
## 🧭 Alignment with Objective
|
||||||
|
- <원래 요청 대비 일치/이탈 평가>
|
||||||
|
## 🕳 Gaps & Missing Evidence
|
||||||
|
- <plan에는 있지만 research가 다루지 않은 항목>
|
||||||
|
## ⚖️ Contradictions / Conflicts
|
||||||
|
- <research 내부 또는 brain context와의 모순; 없으면 "발견되지 않음">
|
||||||
|
## 🚨 Unsupported / Weak Claims
|
||||||
|
- <근거가 빈약하거나 일반화된 진술>
|
||||||
|
## ✅ Guidance for Writer
|
||||||
|
- <Writer가 최종 리포트에서 반드시 보정해야 할 3~5개 구체 지시>
|
||||||
|
- CONSTRAINT: 최대 500단어. 새 지식을 만들지 말고, 제공된 자료에서만 판단할 것.`;
|
||||||
|
|
||||||
|
async execute(input: string, _context?: string, signal?: AbortSignal, options?: AgentExecuteOptions): Promise<string> {
|
||||||
|
const plan = options?.priorResults?.plan || '(plan unavailable)';
|
||||||
|
const research = input;
|
||||||
|
const originalPrompt = options?.priorResults?.originalPrompt || '(original prompt unavailable)';
|
||||||
|
const brainContext = options?.context || '';
|
||||||
|
|
||||||
|
// Reflector 는 중간 단계이므로 비대한 입력을 방지하기 위해 각 섹션을 cap.
|
||||||
|
const cap = (s: string, n: number) => s.length > n ? s.substring(0, n) + '... [trimmed]' : s;
|
||||||
|
|
||||||
|
const wrappedInput = `### SYSTEM INSTRUCTION: SELF-REFLECTION PASS
|
||||||
|
1. Original User Objective:
|
||||||
|
${cap(originalPrompt, 1500)}
|
||||||
|
|
||||||
|
2. Planner Blueprint:
|
||||||
|
${cap(plan, 3000)}
|
||||||
|
|
||||||
|
3. Researcher Output (to be critiqued):
|
||||||
|
${cap(research, 5000)}
|
||||||
|
|
||||||
|
4. Knowledge / Brain Context (for cross-check only — do not invent beyond this):
|
||||||
|
${cap(brainContext, 2000)}
|
||||||
|
|
||||||
|
5. Mission: Run a single rigorous reflection pass and output the structured critique exactly as specified by your persona.`;
|
||||||
return this.callLLM(this.persona, wrappedInput, signal);
|
return this.callLLM(this.persona, wrappedInput, signal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,12 @@ export interface IAgentConfig {
|
|||||||
* Per-agent overrides live in AgentKnowledgeEntry.secondBrainWeight and win.
|
* Per-agent overrides live in AgentKnowledgeEntry.secondBrainWeight and win.
|
||||||
*/
|
*/
|
||||||
knowledgeMixSecondBrainWeight: number;
|
knowledgeMixSecondBrainWeight: number;
|
||||||
|
/**
|
||||||
|
* [Self-Reflection] Researcher와 Writer 사이에 메타인지 단계(Reflector)를 삽입할지 여부.
|
||||||
|
* true(기본): Reflector가 plan/research를 비판적으로 검토한 critique을 Writer에 주입.
|
||||||
|
* false: 기존 3단계(Planner→Researcher→Writer) 그대로 — 1 LLM 호출 절약 (저성능 모델/저지연 우선 시).
|
||||||
|
*/
|
||||||
|
enableReflection: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── 경로 정규화 유틸리티 ───
|
// ─── 경로 정규화 유틸리티 ───
|
||||||
@@ -153,6 +159,7 @@ export function getConfig(): IAgentConfig {
|
|||||||
knowledgeMixSecondBrainWeight: Math.max(0, Math.min(100, Math.round(
|
knowledgeMixSecondBrainWeight: Math.max(0, Math.min(100, Math.round(
|
||||||
cfg.get<number>('knowledgeMix.secondBrainWeight', 50)
|
cfg.get<number>('knowledgeMix.secondBrainWeight', 50)
|
||||||
))),
|
))),
|
||||||
|
enableReflection: cfg.get<boolean>('enableReflection', true),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+34
-3
@@ -49,7 +49,7 @@ export interface IAgent {
|
|||||||
/**
|
/**
|
||||||
* 파이프라인 단계 상태 정의
|
* 파이프라인 단계 상태 정의
|
||||||
*/
|
*/
|
||||||
export type PipelineStage = 'idle' | 'planner' | 'researcher' | 'writer' | 'completed' | 'error';
|
export type PipelineStage = 'idle' | 'planner' | 'researcher' | 'reflector' | 'writer' | 'completed' | 'error';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 감사(Audit) 이력에 기록되는 단일 상태 전환 엔트리.
|
* 감사(Audit) 이력에 기록되는 단일 상태 전환 엔트리.
|
||||||
@@ -449,7 +449,9 @@ export class AgentEngine {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly planner: IAgent,
|
private readonly planner: IAgent,
|
||||||
private readonly researcher: IAgent,
|
private readonly researcher: IAgent,
|
||||||
private readonly writer: IAgent
|
private readonly writer: IAgent,
|
||||||
|
// [Self-Reflection] Researcher와 Writer 사이에 주입되는 메타인지 노드. 미주입 시 기존 3단계 파이프라인을 그대로 유지.
|
||||||
|
private readonly reflector?: IAgent
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -528,6 +530,35 @@ export class AgentEngine {
|
|||||||
// [Structural Fix] 점수가 낮을수록 더 상세한 근거를 요구(comprehensive)하도록 로직 역전
|
// [Structural Fix] 점수가 낮을수록 더 상세한 근거를 요구(comprehensive)하도록 로직 역전
|
||||||
const writerLevel: AbstractionLevel = researchScore < 65 ? 'comprehensive' : 'balanced';
|
const writerLevel: AbstractionLevel = researchScore < 65 ? 'comprehensive' : 'balanced';
|
||||||
|
|
||||||
|
// --- Phase 3.5: Reflector (Self-Reflection) ---
|
||||||
|
// Reflector가 주입되어 있고 옵션에서 명시적으로 끄지 않은 경우에만 실행한다.
|
||||||
|
// 실패해도 파이프라인을 막지 않는다(soft-fail): Reflector는 품질 보강이지 필수 게이트가 아님.
|
||||||
|
let reflection = '';
|
||||||
|
const reflectionDisabled = options?.config?.enableReflection === false;
|
||||||
|
if (this.reflector && !reflectionDisabled) {
|
||||||
|
try {
|
||||||
|
reflection = await this.executeStep(
|
||||||
|
state, 'reflector', '중간 산출물 자기검증 중...',
|
||||||
|
() => this.resilientExecute(state, this.reflector!, 'Reflector', research, brainContext, signal, onProgress, {
|
||||||
|
...options,
|
||||||
|
context: brainContext,
|
||||||
|
signal,
|
||||||
|
config: { ...options?.config, role: 'reflector', isSamePrompt: true },
|
||||||
|
priorResults: { plan, originalPrompt: prompt, ...options?.priorResults },
|
||||||
|
abstractionLevel: 'balanced'
|
||||||
|
}),
|
||||||
|
// [Cache namespace] Writer와 동일한 (research, prompt) 페어를 쓰면 CacheManager가
|
||||||
|
// Writer 호출 시 reflector 결과를 그대로 반환해버린다. 단계명을 prefix로 분리.
|
||||||
|
`reflector::${research}`, prompt, signal, onProgress
|
||||||
|
);
|
||||||
|
} catch (reflErr: any) {
|
||||||
|
// Reflector 실패는 치명적이지 않다. 감사 이력에만 남기고 빈 reflection으로 Writer를 진행시킨다.
|
||||||
|
if (reflErr?.name === 'AbortError') throw reflErr;
|
||||||
|
logError(`[AgentEngine] Reflector soft-fail — Writer 계속 진행: ${reflErr?.message || reflErr}`);
|
||||||
|
reflection = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- Phase 4: Writer ---
|
// --- Phase 4: Writer ---
|
||||||
const finalReport = await this.executeStep(
|
const finalReport = await this.executeStep(
|
||||||
state, 'writer', '최종 리포트 작성 및 편집 중...',
|
state, 'writer', '최종 리포트 작성 및 편집 중...',
|
||||||
@@ -536,7 +567,7 @@ export class AgentEngine {
|
|||||||
context: brainContext,
|
context: brainContext,
|
||||||
signal,
|
signal,
|
||||||
config: { role: 'writer', allowFallback: true, isSamePrompt: true, ...options?.config },
|
config: { role: 'writer', allowFallback: true, isSamePrompt: true, ...options?.config },
|
||||||
priorResults: { plan, writerPrep, previousValidData: state.getResult('finalReport'), ...options?.priorResults },
|
priorResults: { plan, writerPrep, reflection, previousValidData: state.getResult('finalReport'), ...options?.priorResults },
|
||||||
abstractionLevel: writerLevel
|
abstractionLevel: writerLevel
|
||||||
}),
|
}),
|
||||||
research, prompt, signal, onProgress
|
research, prompt, signal, onProgress
|
||||||
|
|||||||
@@ -364,6 +364,142 @@ describe('AgentEngine Integration', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════
|
||||||
|
// Test Suite 4b: Self-Reflection Stage
|
||||||
|
// ═══════════════════════════════════════════════
|
||||||
|
|
||||||
|
class SpyAgent implements IAgent {
|
||||||
|
public callCount = 0;
|
||||||
|
public lastInput: string | undefined;
|
||||||
|
public lastContext: string | undefined;
|
||||||
|
public lastOptions: AgentExecuteOptions | undefined;
|
||||||
|
public calls: { input: string; context?: string; options?: AgentExecuteOptions }[] = [];
|
||||||
|
constructor(private readonly response: string) {}
|
||||||
|
async execute(input: string, context?: string, _signal?: AbortSignal, options?: AgentExecuteOptions): Promise<string> {
|
||||||
|
this.callCount++;
|
||||||
|
this.lastInput = input;
|
||||||
|
this.lastContext = context;
|
||||||
|
this.lastOptions = options;
|
||||||
|
this.calls.push({ input, context, options });
|
||||||
|
return this.response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThrowingAgent implements IAgent {
|
||||||
|
public callCount = 0;
|
||||||
|
constructor(private readonly message: string = '404: model not found') {}
|
||||||
|
async execute(): Promise<string> {
|
||||||
|
this.callCount++;
|
||||||
|
throw new Error(this.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('AgentEngine — Self-Reflection Stage', () => {
|
||||||
|
test('Reflector 주입 시 Researcher와 Writer 사이에 1회 실행되며 결과가 Writer.priorResults.reflection 으로 전달되어야 한다', async () => {
|
||||||
|
const planner = new SpyAgent('Plan: rigorous blueprint covering all objectives.');
|
||||||
|
const researcher = new SpyAgent('Research: dense factual synthesis with supporting evidence.');
|
||||||
|
const reflector = new SpyAgent('## ✅ Guidance for Writer\n- Add missing risk section.');
|
||||||
|
const writer = new SpyAgent('Final report incorporating critique.');
|
||||||
|
|
||||||
|
const engine = new AgentEngine(planner, researcher, writer, reflector);
|
||||||
|
const stages: PipelineStage[] = [];
|
||||||
|
await engine.runMission(
|
||||||
|
'reflect_001', 'Test prompt', 'brain ctx',
|
||||||
|
createAbortSignal(),
|
||||||
|
(stage) => { stages.push(stage); }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 정확히 1회 호출
|
||||||
|
expect(reflector.callCount).toBe(1);
|
||||||
|
// 'reflector' 단계가 onProgress에 등장
|
||||||
|
expect(stages).toContain('reflector');
|
||||||
|
// Stage 순서: planner → researcher → reflector → writer → completed
|
||||||
|
const idxResearcher = stages.indexOf('researcher');
|
||||||
|
const idxReflector = stages.indexOf('reflector');
|
||||||
|
const idxWriter = stages.indexOf('writer');
|
||||||
|
expect(idxResearcher).toBeGreaterThanOrEqual(0);
|
||||||
|
expect(idxReflector).toBeGreaterThan(idxResearcher);
|
||||||
|
expect(idxWriter).toBeGreaterThan(idxReflector);
|
||||||
|
|
||||||
|
// Reflector 입력: research 결과를 input으로 받고 plan/originalPrompt를 priorResults로 받는다
|
||||||
|
expect(reflector.lastInput).toContain('Research: dense factual synthesis');
|
||||||
|
expect(reflector.lastOptions?.priorResults?.plan).toContain('Plan: rigorous blueprint');
|
||||||
|
expect(reflector.lastOptions?.priorResults?.originalPrompt).toBe('Test prompt');
|
||||||
|
|
||||||
|
// Writer 는 (1) writer 단계와 (2) Phase5 generateProactiveAdvice(advisor 모드)에서 각각 1회씩 호출된다.
|
||||||
|
// 첫 번째 호출(메인 writer 단계)이 reflection 을 받았어야 한다.
|
||||||
|
expect(writer.calls.length).toBeGreaterThanOrEqual(1);
|
||||||
|
const writerMainCall = writer.calls.find(c => c.options?.config?.role === 'writer');
|
||||||
|
expect(writerMainCall).toBeDefined();
|
||||||
|
expect(writerMainCall?.options?.priorResults?.reflection).toContain('Guidance for Writer');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Reflector 미주입 시 기존 3단계 파이프라인이 그대로 동작해야 한다 (역호환성)', async () => {
|
||||||
|
const writer = new SpyAgent('Final report without reflection.');
|
||||||
|
const engine = new AgentEngine(
|
||||||
|
new SpyAgent('Plan output of sufficient length to pass validation.'),
|
||||||
|
new SpyAgent('Research output of sufficient length to pass validation.'),
|
||||||
|
writer
|
||||||
|
// reflector 미전달
|
||||||
|
);
|
||||||
|
|
||||||
|
const stages: PipelineStage[] = [];
|
||||||
|
const result = await engine.runMission(
|
||||||
|
'reflect_002', 'Test prompt', 'ctx',
|
||||||
|
createAbortSignal(),
|
||||||
|
(stage) => { stages.push(stage); }
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toContain('Final report without reflection');
|
||||||
|
expect(stages).not.toContain('reflector');
|
||||||
|
// Writer는 reflection 없이도 동작 (priorResults.reflection은 빈 문자열)
|
||||||
|
expect(writer.lastOptions?.priorResults?.reflection ?? '').toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('config.enableReflection=false 옵션으로 Reflector 가 주입돼있어도 스킵되어야 한다', async () => {
|
||||||
|
const reflector = new SpyAgent('should not be called');
|
||||||
|
const writer = new SpyAgent('Final report bypassing reflection.');
|
||||||
|
const engine = new AgentEngine(
|
||||||
|
new SpyAgent('Plan output of sufficient length to pass validation.'),
|
||||||
|
new SpyAgent('Research output of sufficient length to pass validation.'),
|
||||||
|
writer,
|
||||||
|
reflector
|
||||||
|
);
|
||||||
|
|
||||||
|
const stages: PipelineStage[] = [];
|
||||||
|
await engine.runMission(
|
||||||
|
'reflect_003', 'Test prompt', 'ctx',
|
||||||
|
createAbortSignal(),
|
||||||
|
(stage) => { stages.push(stage); },
|
||||||
|
{ config: { enableReflection: false } }
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(reflector.callCount).toBe(0);
|
||||||
|
expect(stages).not.toContain('reflector');
|
||||||
|
// Writer는 정상 실행되고 reflection은 빈 문자열
|
||||||
|
expect(writer.lastOptions?.priorResults?.reflection ?? '').toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Reflector 실패는 soft-fail — Writer 가 빈 critique 으로 진행되어 미션이 완료되어야 한다', async () => {
|
||||||
|
const reflector = new ThrowingAgent('Failed to fetch'); // transient → 재시도 소진 후 throw
|
||||||
|
const writer = new SpyAgent('Final report despite reflector failure.');
|
||||||
|
const engine = new AgentEngine(
|
||||||
|
new SpyAgent('Plan output of sufficient length to pass validation.'),
|
||||||
|
new SpyAgent('Research output of sufficient length to pass validation.'),
|
||||||
|
writer,
|
||||||
|
reflector
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await engine.runMission(
|
||||||
|
'reflect_004', 'Test prompt', 'ctx', createAbortSignal(), noopProgress
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toContain('Final report despite reflector failure');
|
||||||
|
// Writer는 빈 reflection으로 진행되었어야 함
|
||||||
|
expect(writer.lastOptions?.priorResults?.reflection ?? '').toBe('');
|
||||||
|
}, 60000);
|
||||||
|
});
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════
|
// ═══════════════════════════════════════════════
|
||||||
// Test Suite 5: Performance Benchmark
|
// Test Suite 5: Performance Benchmark
|
||||||
// ═══════════════════════════════════════════════
|
// ═══════════════════════════════════════════════
|
||||||
|
|||||||
Reference in New Issue
Block a user