Resolve conflicts by preferring remote changes
This commit is contained in:
@@ -3,20 +3,20 @@
|
||||
<!-- ASTRA:AUTO-START -->
|
||||
|
||||
## Snapshot
|
||||
- **Workspace**: `connectai` `v2.1.2` _(absolute path varies by environment; resolved from the active VS Code workspace)_
|
||||
- **Workspace**: `ConnectAI` `v2.1.2` _(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.
|
||||
- **Stack**: TypeScript, Node.js, VS Code Extension, LM Studio SDK, Test runner
|
||||
- **Stats**: 209 source files, ~36,083 lines across 5 top-level modules.
|
||||
- **Stats**: 205 source files, ~36,036 lines across 5 top-level modules.
|
||||
|
||||
## Last Refresh
|
||||
- **Time**: 2026-05-14T03:14:40.992Z
|
||||
- **Files newly analysed**: 3
|
||||
- **Files reused from cache**: 206
|
||||
- **Time**: 2026-05-13T17:43:53.933Z
|
||||
- **Files newly analysed**: 0
|
||||
- **Files reused from cache**: 205
|
||||
|
||||
## Directory Map
|
||||
```mermaid
|
||||
mindmap
|
||||
root((connectai))
|
||||
root((ConnectAI))
|
||||
src/
|
||||
features/
|
||||
core/
|
||||
@@ -41,7 +41,7 @@ flowchart LR
|
||||
media["media/<br/>6 files"]
|
||||
tests["tests/<br/>27 files"]
|
||||
core_py["core_py/<br/>6 files"]
|
||||
docs["docs/<br/>70 files"]
|
||||
docs["docs/<br/>66 files"]
|
||||
tests --> src
|
||||
```
|
||||
|
||||
@@ -64,14 +64,14 @@ flowchart LR
|
||||
|
||||
## Modules
|
||||
|
||||
### `src/` — 100 files, ~23,880 lines
|
||||
### `src/` — 100 files, ~23,874 lines
|
||||
|
||||
**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/memory/` (8) — Episodic Memory (일화 기억) 과거 대화/회의/결정의 맥락 흐름을 저장합니다. 세션 종료 시 자동으로 에피소드를 요약하여 저장합니다. "왜 이렇게 결정했는지", "어떤 흐름으로 진행했는지" 기록. 저장
|
||||
- `src/retrieval/` (8) — Brain Index — persistent, mtime-keyed tokenized cache of the Second Brain RAG 검색은 매 질의마다 브레인의 모든 .md 파일을 읽고 토크나이즈해서 TF-I
|
||||
- `src/docs/` (6) — Bug: Edited agent.ts Edited agent.ts Edited agent.ts Edited agent.ts Edited agent.ts ...
|
||||
- `src/docs/` (6) — src Chronicle Records
|
||||
- `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)
|
||||
@@ -85,13 +85,13 @@ flowchart LR
|
||||
- `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/sidebarProvider.ts` (3023 lines)
|
||||
- `src/sidebarProvider.ts` (3026 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/retrieval/scoring.ts` (518 lines) — Scoring Engine — TF-IDF + Bilingual Tokenizer 단순 includes() 키워드 매칭을 넘어서, TF-IDF 가중치 기반의 문서 스코어링을 제공합니다. 한국어/영어 양국어 토크나이저를 포함합니다.
|
||||
- `src/skills/agentKnowledgeMap.ts` (374 lines)
|
||||
- `src/core/services.ts` (164 lines)
|
||||
- `src/agent.ts` (3241 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/lib/engine.ts` (880 lines)
|
||||
@@ -107,11 +107,11 @@ flowchart LR
|
||||
- `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/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
|
||||
|
||||
### `media/` — 6 files, ~4,098 lines
|
||||
### `media/` — 6 files, ~4,099 lines
|
||||
|
||||
**Key files**
|
||||
- `media/sidebar.css` (1225 lines) — Stylesheet
|
||||
- `media/sidebar.js` (1873 lines)
|
||||
- `media/sidebar.js` (1874 lines)
|
||||
- `media/sidebar.html` (356 lines) — Astra
|
||||
- `media/settings-panel.css` (210 lines) — Stylesheet
|
||||
- `media/settings-panel.html` (164 lines) — Astra Settings
|
||||
@@ -160,11 +160,11 @@ flowchart LR
|
||||
- `core_py/optimizer.py` (55 lines)
|
||||
- `core_py/queue_worker.py` (82 lines)
|
||||
|
||||
### `docs/` — 70 files, ~2,758 lines
|
||||
### `docs/` — 66 files, ~2,716 lines
|
||||
|
||||
**Sub-directories**
|
||||
- `docs/records/` (58) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 프로젝트 코드 리뷰 해줄 수 있어? 개선할 부분이 있는지, 그러고...
|
||||
- `docs/docs/` (5) — Bug: Viewed integrationretrieval.test.ts:1-59 integrationretrieval.test.ts를 통해 ...
|
||||
- `docs/records/` (54) — Astra Project Chronicle Records
|
||||
- `docs/docs/` (5) — docs Chronicle Records
|
||||
|
||||
**Key files**
|
||||
- `docs/TELEGRAM_REMOTE_EXECUTION_PLAN.md` (452 lines) — Telegram Remote Execution 기획서
|
||||
@@ -172,26 +172,26 @@ flowchart LR
|
||||
- `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-03_connectai_project_knowledge_overview.md` (121 lines) — Astra Project Knowledge Overview
|
||||
- `docs/records/ConnectAI/timeline.md` (146 lines) — Project Timeline
|
||||
- `docs/records/ConnectAI/timeline.md` (134 lines) — Project Timeline
|
||||
- `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/UX_UI_Consistency_Guidelines.md` (44 lines) — UX/UI Consistency Guidelines
|
||||
- `docs/docs/records/docs/README.md` (18 lines) — docs Chronicle Records
|
||||
- `docs/docs/records/docs/bugs/BUG-0001-viewed-integration-retrieval-test-ts-1-59-integration-retrie.md` (16 lines) — Bug: Viewed integrationretrieval.test.ts:1-59 integrationretrieval.test.ts를 통해 ...
|
||||
- `docs/docs/records/docs/chronicle.config.json` (11 lines) — JSON configuration
|
||||
- `docs/docs/records/docs/project-profile.md` (31 lines) — Project Profile
|
||||
- `docs/docs/records/docs/README.md` (18 lines) — docs Chronicle Records
|
||||
- `docs/docs/records/docs/timeline.md` (7 lines) — Project Timeline
|
||||
- `docs/PROJECT_CHRONICLE_GUARD_ROADMAP.md` (43 lines) — Project Chronicle Guard: Search Engine Roadmap
|
||||
- `docs/records/ConnectAI/bugs/BUG-0001-volumes-data-project-antigravity-connectai-프로젝트-코드-리뷰-해줄-수-있.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 프로젝트 코드 리뷰 해줄 수 있어? 개선할 부분이 있는지, 그러고...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0002-지금-내가-분석-요청하고-너가-답을-줄때-아래-템플릿에-맞춰-답을-써주고-있는데-개선-포인트가-있는지-확인해.md` (16 lines) — Bug: 지금 내가 분석 요청하고 너가 답을 줄때 아래 템플릿에 맞춰 답을 써주고 있는데, 개선 포인트가 있는지 확인해줘. ## 내가 보는 위험 가장 큰...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0003-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0004-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0005-다시한번-답줘-volumes-data-project-antigravity-connectai-내-질문에-대한-.md` (16 lines) — Bug: 다시한번 답줘. /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0006-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0007-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0008-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0009-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md` (16 lines) — Bug: 문제점을 읽고 어떻게 개선하는게 최선인지 분석해주면 좋겠어. 알겠습니다. 지금부터 ConnectAI 프로젝트에만 완전히 집중하겠습니다. ...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0010-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md` (16 lines) — Bug: 문제점을 읽고 어떻게 개선하는게 최선인지 분석해주면 좋겠어. 알겠습니다. 지금부터 ConnectAI 프로젝트에만 완전히 집중하겠습니다. ...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0011-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md` (16 lines) — Bug: 문제점을 읽고 어떻게 개선하는게 최선인지 분석해주면 좋겠어. 알겠습니다. 지금부터 ConnectAI 프로젝트에만 완전히 집중하겠습니다. ...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0012-질문이-있어-논문을-쓰려고해-논문-주제는-서비스적이-아닌-사용자가-ai에게-구조로-질문을-해야-사용자의-의도.md` (16 lines) — Bug: 질문이 있어. 논문을 쓰려고해. 논문 주제는 서비스적이 아닌 사용자가 ai에게 구조로 질문을 해야 사용자의 의도에 맞는 답변을 받을 수 있을까야...
|
||||
- `docs/records/ConnectAI/README.md` (18 lines) — Astra Project Chronicle Records
|
||||
- `docs/records/ConnectAI/bugs/BUG-0001-volumes-data-project-antigravity-connectai-프로젝트-코드-리뷰-해줄-수-있.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 프로젝트 코드 리뷰 해줄 수 있어? 개선할 부분이 있는지, 그러고...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0002-지금-내가-분석-요청하고-너가-답을-줄때-아래-템플릿에-맞춰-답을-써주고-있는데-개선-포인트가-있는지-확인해.md` (16 lines) — Bug: 지금 내가 분석 요청하고 너가 답을 줄때 아래 템플릿에 맞춰 답을 써주고 있는데, 개선 포인트가 있는지 확인해줘. ## 내가 보는 위험 가장 큰...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0003-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0004-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0005-다시한번-답줘-volumes-data-project-antigravity-connectai-내-질문에-대한-.md` (16 lines) — Bug: 다시한번 답줘. /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0006-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0007-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0008-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md` (16 lines) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0009-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md` (16 lines) — Bug: 문제점을 읽고 어떻게 개선하는게 최선인지 분석해주면 좋겠어. 알겠습니다. 지금부터 ConnectAI 프로젝트에만 완전히 집중하겠습니다. ...
|
||||
- `docs/records/ConnectAI/bugs/BUG-0010-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md` (16 lines) — Bug: 문제점을 읽고 어떻게 개선하는게 최선인지 분석해주면 좋겠어. 알겠습니다. 지금부터 ConnectAI 프로젝트에만 완전히 집중하겠습니다. ...
|
||||
|
||||
## VS Code Extension Surface
|
||||
- **Extension ID**: `g1nation.astra`
|
||||
@@ -307,7 +307,7 @@ Astra는 대표님의 명시적인 승인 하에 로컬 시스템의 강력한
|
||||
**Designed for High-Performance Decision Making.**
|
||||
Copyright (C) **g1nation**. All rights reserved.
|
||||
|
||||
_Last auto-scan: 2026-05-14T03:14:40.992Z · signature `1f7ace87`_
|
||||
_Last auto-scan: 2026-05-13T17:43:53.933Z · signature `5020e02c`_
|
||||
<!-- ASTRA:AUTO-END -->
|
||||
|
||||
## Purpose
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"projectId": "connectai",
|
||||
"projectName": "connectai",
|
||||
"projectRoot": "E:\\Wiki\\connectai",
|
||||
"recordRoot": "E:\\Wiki\\connectai\\docs\\records\\connectai",
|
||||
"projectName": "ConnectAI",
|
||||
"projectRoot": "/Volumes/Data/project/Antigravity/ConnectAI",
|
||||
"recordRoot": "/Volumes/Data/project/Antigravity/ConnectAI/docs/records/ConnectAI",
|
||||
"description": "Auto-created by Project Architecture activation.",
|
||||
"corePurpose": "",
|
||||
"detailLevel": "standard",
|
||||
"createdAt": "2026-05-14T00:57:32.245Z",
|
||||
"updatedAt": "2026-05-14T04:39:56.139Z"
|
||||
"createdAt": "2026-05-13T13:09:33.788Z",
|
||||
"updatedAt": "2026-05-14T12:42:12.047Z"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Feature Plan: Connectai architecture 문서 최신화 해줘.
|
||||
|
||||
## 1. Feature Name
|
||||
Connectai architecture 문서 최신화 해줘.
|
||||
|
||||
## 2. Reason
|
||||
Capture the current planning or architecture direction before implementation continues.
|
||||
|
||||
## 3. Original User Request
|
||||
Connectai architecture 문서 최신화 해줘.
|
||||
|
||||
## 4. Interpreted User Intent
|
||||
Connectai architecture 문서 최신화 해줘.
|
||||
|
||||
## 5. Background
|
||||
문서의 최신화를 위해 현재 내용과 업데이트 방향에 대한 구체적인 요구사항이 필요합니다.
|
||||
|
||||
## 6. Scope
|
||||
- Continue from the active project conversation.
|
||||
- Use the selected project record folder automatically.
|
||||
|
||||
## 7. Out Of Scope
|
||||
- Manual record type selection.
|
||||
- Blocking the user with record-writing prompts.
|
||||
|
||||
## 8. Development Direction
|
||||
문서의 최신화를 위해 현재 내용과 업데이트 방향에 대한 구체적인 요구사항이 필요합니다.
|
||||
|
||||
## 9. Dependency Strategy
|
||||
Prefer existing project modules and local Markdown records.
|
||||
|
||||
## 10. Expected Value
|
||||
Future work can resume with the latest project intent and reasoning preserved.
|
||||
|
||||
## 11. Success Criteria
|
||||
- The record is saved automatically after a meaningful project turn.
|
||||
- The record stays under the active project.
|
||||
|
||||
## 12. Developer Instruction
|
||||
Use this record as lightweight context for the next development or review pass.
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
# Feature Plan: 지금 connectai architecture.md 문서 내용 중 업데이트가 필요한 부분이 있는지 확인해줘. 그러고 최신화해줘. 너가 분석해
|
||||
|
||||
## 1. Feature Name
|
||||
지금 connectai architecture.md 문서 내용 중 업데이트가 필요한 부분이 있는지 확인해줘. 그러고 최신화해줘. 너가 분석해
|
||||
|
||||
## 2. Reason
|
||||
Capture the current planning or architecture direction before implementation continues.
|
||||
|
||||
## 3. Original User Request
|
||||
지금 connectai architecture.md 문서 내용 중 업데이트가 필요한 부분이 있는지 확인해줘. 그러고 최신화해줘. 너가 분석해
|
||||
|
||||
## 4. Interpreted User Intent
|
||||
지금 connectai architecture.md 문서 내용 중 업데이트가 필요한 부분이 있는지 확인해줘. 그러고 최신화해줘. 너가 분석해
|
||||
|
||||
## 5. Background
|
||||
제가 분석을 수행하려면 먼저 `ARCHITECTURE_ANALYSIS.md` 파일의 실제 내용이 필요합니다. 이전 확인 결과, 해당 파일을 읽는 과정에서 접근에 실패했거나 내용을 확인할 수 없었습니다. 따라서 제가 문서의 최신화 작업을 시작하고 어떤 부분을 업데이트해야 할지 판단하기 위해서는 **해당 파일의 전체 내용을 제공**해 주시거나, 파일이 실제로 접근 가능한 상태인지 다시 확인해 주셔야 합니다. 파일 내용을 제공해 주시면, 그 내용을 바탕으로 현재 프로젝트 상황과 기술적 맥락을 고려하여 최신화 방향과 구체적인 수정 사항을 제시해 드리겠습니다.
|
||||
|
||||
## 6. Scope
|
||||
- Continue from the active project conversation.
|
||||
- Use the selected project record folder automatically.
|
||||
|
||||
## 7. Out Of Scope
|
||||
- Manual record type selection.
|
||||
- Blocking the user with record-writing prompts.
|
||||
|
||||
## 8. Development Direction
|
||||
제가 분석을 수행하려면 먼저 `ARCHITECTURE_ANALYSIS.md` 파일의 실제 내용이 필요합니다. 이전 확인 결과, 해당 파일을 읽는 과정에서 접근에 실패했거나 내용을 확인할 수 없었습니다. 따라서 제가 문서의 최신화 작업을 시작하고 어떤 부분을 업데이트해야 할지 판단하기 위해서는 **해당 파일의 전체 내용을 제공**해 주시거나, 파일이 실제로 접근 가능한 상태인지 다시 확인해 주셔야 합니다. 파일 내용을 제공해 주시면, 그 내용을 바탕으로 현재 프로젝트 상황과 기술적 맥락을 고려하여 최신화 방향과 구체적인 수정 사항을 제시해 드리겠습니다.
|
||||
|
||||
## 9. Dependency Strategy
|
||||
Prefer existing project modules and local Markdown records.
|
||||
|
||||
## 10. Expected Value
|
||||
Future work can resume with the latest project intent and reasoning preserved.
|
||||
|
||||
## 11. Success Criteria
|
||||
- The record is saved automatically after a meaningful project turn.
|
||||
- The record stays under the active project.
|
||||
|
||||
## 12. Developer Instruction
|
||||
Use this record as lightweight context for the next development or review pass.
|
||||
@@ -127,23 +127,8 @@
|
||||
## 2026-05-13
|
||||
- Auto development record created: development/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업할거야_implementation.md
|
||||
|
||||
## 2026-05-14
|
||||
- Auto decision record created: decisions\ADR-0011-e-wiki-connectai-self-reflection-기능이-있는데-어떻게-self-reflection.md
|
||||
## 2026-05-13
|
||||
- Auto planning record created: planning/2026-05-13_connectai-architecture-문서-최신화-해줘.md
|
||||
|
||||
## 2026-05-14
|
||||
- Auto decision record created: decisions\ADR-0012-e-wiki-connectai-self-reflection-기능이-있는데-어떻게-self-reflection.md
|
||||
|
||||
## 2026-05-14
|
||||
- Auto development record created: development\2026-05-14_reflector-에이전트가-1인-기업-에이전트-목록에는-안보이는데_implementation.md
|
||||
|
||||
## 2026-05-14
|
||||
- Auto bug record created: bugs\BUG-0012-질문이-있어-논문을-쓰려고해-논문-주제는-서비스적이-아닌-사용자가-ai에게-구조로-질문을-해야-사용자의-의도.md
|
||||
|
||||
## 2026-05-14
|
||||
- Auto bug record created: bugs\BUG-0013-thesis-paper를-쓰려고-하는데-아래와-같이-쓰면-좋을까-이런-식으로-쓰면-되지-않을까-싶음-1-in.md
|
||||
|
||||
## 2026-05-14
|
||||
- Auto bug record created: bugs\BUG-0014-논문-outline-title-인간-ai-상호작용에서-의도-정렬을-높이기-위한-최소-질의-구조-연구-또는-사.md
|
||||
|
||||
## 2026-05-14
|
||||
- Auto discussion record created: discussions\2026-05-14_최성연-알아-칼리버스에서-근무한데.md
|
||||
## 2026-05-13
|
||||
- Auto planning record created: planning/2026-05-13_지금-connectai-architecture-md-문서-내용-중-업데이트가-필요한-부분이-있는지-확인해줘-.md
|
||||
|
||||
@@ -749,12 +749,24 @@
|
||||
margin: 4px 0;
|
||||
font-size: 10.5px;
|
||||
color: var(--text-primary);
|
||||
opacity: 1;
|
||||
transition: opacity 600ms ease, margin 600ms ease, padding 600ms ease, max-height 600ms ease;
|
||||
max-height: 80px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.arch-refresh-card .arc-head {
|
||||
color: var(--text-bright); font-weight: 600; margin-bottom: 2px;
|
||||
}
|
||||
.arch-refresh-card .arc-meta { color: var(--text-dim); font-size: 9.5px; }
|
||||
.arch-refresh-card.no-changes { border-style: dashed; }
|
||||
.arch-refresh-card.fading {
|
||||
opacity: 0;
|
||||
max-height: 0;
|
||||
margin: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* Inline model picker that lives in the input footer, next to the attach
|
||||
button. Replaces the (now-removed) bottom model row + the separate
|
||||
|
||||
@@ -932,6 +932,10 @@
|
||||
if (chatEl) {
|
||||
chatEl.appendChild(card);
|
||||
chatEl.scrollTop = chatEl.scrollHeight;
|
||||
setTimeout(() => {
|
||||
card.classList.add('fading');
|
||||
card.addEventListener('transitionend', () => card.remove(), { once: true });
|
||||
}, 3000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -416,6 +416,11 @@
|
||||
"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."
|
||||
},
|
||||
"g1nation.autoLessonFromReflection": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Persist substantive Reflector critiques to the active brain as lesson cards under `lessons/auto-reflector/`. Future missions automatically retrieve these cards (via the existing Experience-Memory pipeline) and inject them as ‘[⚠ ACTIVE LESSONS — verify these BEFORE finalizing]’ guardrails into Planner/Researcher/Writer context. A repeated critique (similar title) bumps `occurrences` and escalates `severity` (low→medium→high) instead of duplicating the card, so recurring patterns get louder over time. Disable to keep critiques single-mission only."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
/**
|
||||
* ============================================================
|
||||
* Reflection → Lesson persistence
|
||||
*
|
||||
* Take the Reflector agent's structured critique and persist any substantive
|
||||
* findings as a `lesson` card in `<brainDir>/lessons/auto-reflector/`. The
|
||||
* existing brain retrieval pipeline (see `retrieval/brainIndex.ts` +
|
||||
* `retrieval/lessonHelpers.ts`) then automatically boosts these cards and
|
||||
* injects them as an `[⚠ ACTIVE LESSONS — verify these BEFORE finalizing your
|
||||
* answer]` block in *future* missions' Planner/Researcher/Writer context, so a
|
||||
* critique caught in mission N becomes a guardrail in mission N+1.
|
||||
*
|
||||
* Recurrence handling: if a similarly-titled auto-reflector lesson already
|
||||
* exists, we bump `occurrences:` and escalate `severity` (low→medium→high)
|
||||
* instead of producing a duplicate card. Same pattern reappearing 3+ times
|
||||
* surfaces as severity:high, which the lesson retrieval/scoring layer
|
||||
* propagates as a stronger guardrail.
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { logInfo, logError } from '../utils';
|
||||
import {
|
||||
lessonSlug,
|
||||
parseLessonFrontmatter,
|
||||
bumpLessonOccurrences,
|
||||
normalizeLessonTitle,
|
||||
} from '../retrieval/lessonHelpers';
|
||||
|
||||
interface ReflectionSections {
|
||||
alignment: string;
|
||||
gaps: string;
|
||||
contradictions: string;
|
||||
unsupported: string;
|
||||
guidance: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull the body of a `## …<keyword>…` section out of the Reflector's markdown. Line-scan rather
|
||||
* than a multi-line regex so it survives emoji headers and trailing whitespace without
|
||||
* leaning on JS-unsupported regex features.
|
||||
*/
|
||||
function extractSection(text: string, headerKeyword: string): string {
|
||||
if (!text) return '';
|
||||
const kw = headerKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const headerRe = new RegExp(`^##[^\\n]*${kw}[^\\n]*$`, 'i');
|
||||
const lines = text.split(/\r?\n/);
|
||||
const buf: string[] = [];
|
||||
let inSection = false;
|
||||
for (const line of lines) {
|
||||
if (headerRe.test(line)) { inSection = true; continue; }
|
||||
if (inSection && /^##\s/.test(line)) break;
|
||||
if (inSection) buf.push(line);
|
||||
}
|
||||
return buf.join('\n').trim();
|
||||
}
|
||||
|
||||
function parseReflection(text: string): ReflectionSections {
|
||||
return {
|
||||
alignment: extractSection(text, 'Alignment'),
|
||||
gaps: extractSection(text, 'Gaps'),
|
||||
contradictions: extractSection(text, 'Contradictions'),
|
||||
unsupported: extractSection(text, 'Unsupported'),
|
||||
guidance: extractSection(text, 'Guidance'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* "Trivial" = the Reflector explicitly said nothing was found, or the section is too short to be
|
||||
* meaningful. We don't want to spam the brain with `발견되지 않음` cards.
|
||||
*/
|
||||
function isTrivial(section: string): boolean {
|
||||
if (!section) return true;
|
||||
const stripped = section.replace(/[-*•·\s\n]+/g, '').toLowerCase();
|
||||
if (!stripped) return true;
|
||||
if (/^(없음|발견되지않음|해당없음|na|nothing|none|n\/a)$/.test(stripped)) return true;
|
||||
if (stripped.length < 12) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function hasSubstantiveContent(sections: ReflectionSections): boolean {
|
||||
return !isTrivial(sections.gaps)
|
||||
|| !isTrivial(sections.contradictions)
|
||||
|| !isTrivial(sections.unsupported)
|
||||
|| !isTrivial(sections.guidance);
|
||||
}
|
||||
|
||||
/** Pick a short (≤80 char) title from the first actionable bullet across the substantive sections. */
|
||||
function deriveTitle(sections: ReflectionSections): string {
|
||||
const order = [sections.guidance, sections.gaps, sections.unsupported, sections.contradictions];
|
||||
for (const sec of order) {
|
||||
if (isTrivial(sec)) continue;
|
||||
const firstBullet = sec.split('\n').find((l) => /^\s*[-*•]/.test(l));
|
||||
const raw = (firstBullet || sec.split('\n')[0] || '').replace(/^\s*[-*•]\s*/, '').trim();
|
||||
if (raw.length >= 10) {
|
||||
return raw.length > 80 ? raw.slice(0, 77) + '…' : raw;
|
||||
}
|
||||
}
|
||||
return 'Reflector finding (auto)';
|
||||
}
|
||||
|
||||
function severityFor(occurrences: number): 'low' | 'medium' | 'high' {
|
||||
if (occurrences >= 3) return 'high';
|
||||
if (occurrences >= 2) return 'medium';
|
||||
return 'low';
|
||||
}
|
||||
|
||||
function buildLessonCard(params: {
|
||||
title: string;
|
||||
today: string;
|
||||
situation: string;
|
||||
sections: ReflectionSections;
|
||||
severity: 'low' | 'medium' | 'high';
|
||||
}): string {
|
||||
const { title, today, situation, sections, severity } = params;
|
||||
const safeTitle = title.replace(/\n/g, ' ').trim();
|
||||
|
||||
const riskParts = [
|
||||
isTrivial(sections.gaps) ? '' : `**Gaps**\n${sections.gaps.trim()}`,
|
||||
isTrivial(sections.unsupported) ? '' : `**Unsupported claims**\n${sections.unsupported.trim()}`,
|
||||
isTrivial(sections.contradictions) ? '' : `**Contradictions**\n${sections.contradictions.trim()}`,
|
||||
].filter(Boolean);
|
||||
const risk = riskParts.length ? riskParts.join('\n\n') : '<critique 본문 비어 있음>';
|
||||
|
||||
const rootCause = isTrivial(sections.alignment)
|
||||
? '<원본 요청 대비 이탈/근본 원인이 critique에 명시되지 않음 — 회고 시 보강>'
|
||||
: sections.alignment.trim();
|
||||
|
||||
const fix = isTrivial(sections.guidance)
|
||||
? '<Reflector가 Writer 보정 지시(Guidance)를 비워뒀음 — 다음 미션 시 수동 보강 권장>'
|
||||
: sections.guidance.trim();
|
||||
|
||||
const bullets = isTrivial(sections.guidance)
|
||||
? []
|
||||
: sections.guidance
|
||||
.split('\n')
|
||||
.map((l) => l.trim())
|
||||
.filter((l) => /^[-*•]/.test(l))
|
||||
.map((l) => l.replace(/^[-*•]\s*/, ''))
|
||||
.filter((l) => l.length > 0)
|
||||
.slice(0, 6);
|
||||
const checklistBlock = (bullets.length
|
||||
? bullets
|
||||
: ['<다음 유사 mission 전에 위 Gaps / Unsupported 항목을 사전 점검>']
|
||||
).map((c) => `- ${c}`).join('\n');
|
||||
|
||||
return [
|
||||
'---',
|
||||
'type: lesson',
|
||||
`title: ${safeTitle}`,
|
||||
'applies-to: []',
|
||||
`severity: ${severity}`,
|
||||
'source: auto-reflector',
|
||||
'occurrences: 1',
|
||||
`last-seen: ${today}`,
|
||||
'---',
|
||||
'',
|
||||
`# Lesson: ${safeTitle}`,
|
||||
'',
|
||||
'## Situation',
|
||||
situation,
|
||||
'',
|
||||
'## Mistake / Risk',
|
||||
risk,
|
||||
'',
|
||||
'## Root Cause',
|
||||
rootCause,
|
||||
'',
|
||||
'## Fix',
|
||||
fix,
|
||||
'',
|
||||
'## Prevention Checklist',
|
||||
checklistBlock,
|
||||
'',
|
||||
'## Applies To',
|
||||
'- auto-reflector',
|
||||
'',
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Cheap title-overlap match against existing auto-reflector cards. Exact-normalized-title hit wins
|
||||
* outright; otherwise the best ≥60% term-overlap candidate is returned (or none).
|
||||
*/
|
||||
function findExistingLesson(autoDir: string, newTitle: string): { filePath: string; content: string } | undefined {
|
||||
let entries: string[];
|
||||
try {
|
||||
entries = fs.readdirSync(autoDir).filter((f) => f.endsWith('.md'));
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
const newNorm = normalizeLessonTitle(newTitle);
|
||||
if (!newNorm) return undefined;
|
||||
const tokenize = (norm: string) => new Set(norm.match(/[a-z0-9]{3,}|[가-힣]{2,}/g) || []);
|
||||
const newTerms = tokenize(newNorm);
|
||||
|
||||
let best: { filePath: string; content: string; score: number } | undefined;
|
||||
for (const f of entries) {
|
||||
const filePath = path.join(autoDir, f);
|
||||
let content = '';
|
||||
try {
|
||||
content = fs.readFileSync(filePath, 'utf8');
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
const fm = parseLessonFrontmatter(content);
|
||||
const existingTitle = (fm.title || '').trim();
|
||||
const existingNorm = normalizeLessonTitle(existingTitle);
|
||||
if (!existingNorm) continue;
|
||||
if (existingNorm === newNorm) return { filePath, content };
|
||||
if (newTerms.size === 0) continue;
|
||||
const existingTerms = tokenize(existingNorm);
|
||||
let overlap = 0;
|
||||
for (const t of newTerms) if (existingTerms.has(t)) overlap++;
|
||||
const score = overlap / newTerms.size;
|
||||
if (score >= 0.6 && (!best || score > best.score)) {
|
||||
best = { filePath, content, score };
|
||||
}
|
||||
}
|
||||
return best ? { filePath: best.filePath, content: best.content } : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace (or insert) the `severity:` line in a lesson's frontmatter. Returns content unchanged if
|
||||
* there is no frontmatter block — caller is responsible for not calling on free-form notes.
|
||||
*/
|
||||
function setSeverityInFrontmatter(content: string, severity: 'low' | 'medium' | 'high'): string {
|
||||
if (!/^?---\s*\n/.test(content)) return content;
|
||||
const end = content.indexOf('\n---', 4);
|
||||
if (end < 0) return content;
|
||||
let block = content.slice(0, end);
|
||||
const rest = content.slice(end);
|
||||
if (/^\s*severity\s*:/m.test(block)) {
|
||||
block = block.replace(/^(\s*severity\s*:\s*).*$/m, `$1${severity}`);
|
||||
} else {
|
||||
block += `\nseverity: ${severity}`;
|
||||
}
|
||||
return block + rest;
|
||||
}
|
||||
|
||||
export interface PersistResult {
|
||||
/** Absolute path of the file written or bumped. */
|
||||
filePath: string;
|
||||
/** True if an existing lesson was updated (occurrences++); false for a new card. */
|
||||
bumped: boolean;
|
||||
/** Current occurrences value after the operation. */
|
||||
occurrences: number;
|
||||
/** Current severity after the operation. */
|
||||
severity: 'low' | 'medium' | 'high';
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the Reflector's critique as a lesson card. Returns `undefined` when nothing was written
|
||||
* (no brain path, critique trivial, IO failure — all soft-fail by design; never throws).
|
||||
*/
|
||||
export function persistReflectionAsLesson(params: {
|
||||
reflection: string;
|
||||
originalPrompt: string;
|
||||
brainDir: string;
|
||||
}): PersistResult | undefined {
|
||||
const { reflection, originalPrompt, brainDir } = params;
|
||||
if (!reflection || !brainDir || !path.isAbsolute(brainDir)) return undefined;
|
||||
|
||||
try {
|
||||
const sections = parseReflection(reflection);
|
||||
if (!hasSubstantiveContent(sections)) {
|
||||
logInfo('[reflectionPersister] critique is trivial — skipping lesson dump.');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
const title = deriveTitle(sections);
|
||||
const autoDir = path.join(brainDir, 'lessons', 'auto-reflector');
|
||||
try {
|
||||
fs.mkdirSync(autoDir, { recursive: true });
|
||||
} catch {
|
||||
// Fall through; the write below will surface the real failure.
|
||||
}
|
||||
|
||||
const existing = findExistingLesson(autoDir, title);
|
||||
if (existing) {
|
||||
let bumped = bumpLessonOccurrences(existing.content, today);
|
||||
const newOcc = parseLessonFrontmatter(bumped).occurrences ?? 1;
|
||||
const sev = severityFor(newOcc);
|
||||
bumped = setSeverityInFrontmatter(bumped, sev);
|
||||
fs.writeFileSync(existing.filePath, bumped, 'utf8');
|
||||
logInfo(`[reflectionPersister] bumped existing lesson (occ=${newOcc}, severity=${sev}): ${existing.filePath}`);
|
||||
return { filePath: existing.filePath, bumped: true, occurrences: newOcc, severity: sev };
|
||||
}
|
||||
|
||||
const situation = (originalPrompt || '').slice(0, 400).replace(/\s+/g, ' ').trim()
|
||||
|| '<original prompt unavailable>';
|
||||
const card = buildLessonCard({ title, today, situation, sections, severity: 'low' });
|
||||
|
||||
let filePath = path.join(autoDir, `${today}-${lessonSlug(title)}.md`);
|
||||
let n = 2;
|
||||
while (fs.existsSync(filePath)) {
|
||||
filePath = path.join(autoDir, `${today}-${lessonSlug(title)}-${n++}.md`);
|
||||
}
|
||||
fs.writeFileSync(filePath, card, 'utf8');
|
||||
logInfo(`[reflectionPersister] new lesson saved: ${filePath}`);
|
||||
return { filePath, bumped: false, occurrences: 1, severity: 'low' };
|
||||
} catch (e: any) {
|
||||
logError('[reflectionPersister] failed to persist lesson.', { error: e?.message ?? String(e) });
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -73,6 +73,13 @@ export interface IAgentConfig {
|
||||
* false: 기존 3단계(Planner→Researcher→Writer) 그대로 — 1 LLM 호출 절약 (저성능 모델/저지연 우선 시).
|
||||
*/
|
||||
enableReflection: boolean;
|
||||
/**
|
||||
* [Self-Reflection → Knowledge] Reflector critique 중 의미 있는 발견을 brain의
|
||||
* `lessons/auto-reflector/`에 lesson 카드로 영속화할지 여부. true(기본)이면 동일/유사 패턴이
|
||||
* 다음 미션에서 retrieval로 자동 주입되고, 같은 critique이 반복될수록 occurrences/severity가
|
||||
* 누적됨. false면 critique은 그 미션 한정으로만 사용되고 사라짐.
|
||||
*/
|
||||
autoLessonFromReflection: boolean;
|
||||
}
|
||||
|
||||
// ─── 경로 정규화 유틸리티 ───
|
||||
@@ -160,6 +167,7 @@ export function getConfig(): IAgentConfig {
|
||||
cfg.get<number>('knowledgeMix.secondBrainWeight', 50)
|
||||
))),
|
||||
enableReflection: cfg.get<boolean>('enableReflection', true),
|
||||
autoLessonFromReflection: cfg.get<boolean>('autoLessonFromReflection', true),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+27
-1
@@ -4,10 +4,12 @@ import * as path from 'path';
|
||||
import { createHash } from 'crypto';
|
||||
import { lockManager } from '../core/lock';
|
||||
import { actionQueue } from '../core/queue';
|
||||
import { logInfo, logError } from '../utils';
|
||||
import { logInfo, logError, getActiveBrainProfile } from '../utils';
|
||||
import { AgentDataValidator, PerformanceProfiler, CognitionAudit } from './diagnostics';
|
||||
import { WikiFormatter } from './formatter';
|
||||
import { ErrorType, RecoveryRule } from '../types/interfaces';
|
||||
import { getConfig } from '../config';
|
||||
import { persistReflectionAsLesson } from '../agents/reflectionPersister';
|
||||
export { ErrorType, RecoveryRule };
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
@@ -557,6 +559,30 @@ export class AgentEngine {
|
||||
logError(`[AgentEngine] Reflector soft-fail — Writer 계속 진행: ${reflErr?.message || reflErr}`);
|
||||
reflection = '';
|
||||
}
|
||||
|
||||
// [Self-Reflection → Knowledge] Reflector가 의미 있는 critique을 내놓았으면
|
||||
// brain에 lesson 카드로 영속화한다. 다음 미션의 Planner/Researcher/Writer는
|
||||
// 기존 lesson retrieval 경로를 통해 이 카드를 자동으로 inject받는다.
|
||||
// 동일 패턴 재발 시 카드를 새로 만들지 않고 occurrences를 증가시키며 severity를
|
||||
// low→medium→high로 가중. fire-and-forget으로 미션 흐름을 막지 않는다.
|
||||
if (reflection && getConfig().autoLessonFromReflection !== false) {
|
||||
try {
|
||||
const brainDir = getActiveBrainProfile()?.localBrainPath;
|
||||
if (brainDir) {
|
||||
const result = persistReflectionAsLesson({
|
||||
reflection,
|
||||
originalPrompt: prompt,
|
||||
brainDir,
|
||||
});
|
||||
if (result) {
|
||||
logInfo(`[AgentEngine] Reflector critique → lesson (${result.bumped ? 'bumped' : 'new'}, severity=${result.severity}, occ=${result.occurrences}).`);
|
||||
}
|
||||
}
|
||||
} catch (persistErr: any) {
|
||||
// Lesson 영속화 실패는 미션 결과에 영향 없음 — 로그만 남기고 계속 진행.
|
||||
logError(`[AgentEngine] lesson 영속화 실패 (무시): ${persistErr?.message || persistErr}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Phase 4: Writer ---
|
||||
|
||||
Reference in New Issue
Block a user