diff --git a/.astra/project-context/architecture.md b/.astra/project-context/architecture.md
index a9f29c7..c7f9aac 100644
--- a/.astra/project-context/architecture.md
+++ b/.astra/project-context/architecture.md
@@ -3,20 +3,20 @@
## Snapshot
-- **Workspace**: `ConnectAI` `v2.2.19` _(absolute path varies by environment; resolved from the active VS Code workspace)_
+- **Workspace**: `connectai` `v2.2.60` _(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**: 265 source files, ~52,981 lines across 5 top-level modules.
+- **Stats**: 271 source files, ~55,157 lines across 5 top-level modules.
## Last Refresh
-- **Time**: 2026-05-17T14:50:50.535Z
-- **Files newly analysed**: 5
-- **Files reused from cache**: 260
+- **Time**: 2026-05-22T06:00:02.986Z
+- **Files newly analysed**: 1
+- **Files reused from cache**: 270
## Directory Map
```mermaid
mindmap
- root((ConnectAI))
+ root((connectai))
src/
features/
core/
@@ -31,17 +31,18 @@ mindmap
docs/
records/
docs/
+ Meeting/
```
## Module Dependencies
> Arrows: which top-level module imports from which.
```mermaid
flowchart LR
- src["src/
137 files"]
+ src["src/
139 files"]
media["media/
6 files"]
tests["tests/
35 files"]
core_py["core_py/
6 files"]
- docs["docs/
81 files"]
+ docs["docs/
85 files"]
tests --> src
```
@@ -53,7 +54,7 @@ flowchart LR
## Hub Files
> Imported by many other files — touching these has wide blast radius.
-- `src/utils.ts` — referenced by **49** files
+- `src/utils.ts` — referenced by **50** files
- `src/config.ts` — referenced by **16** files
- `src/features/company/types.ts` — referenced by **13** 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/core/services.ts` — referenced by **10** files
@@ -64,14 +65,14 @@ flowchart LR
## Modules
-### `src/` — 137 files, ~36,157 lines
+### `src/` — 139 files, ~38,157 lines
**Sub-directories**
-- `src/features/` (64) — Astra Office — public API. 다음 세션에서 추가될 OfficeSnapshot presenter / schema 도 같은 entry 로 노출 예정. 현재 노출: full webview panel H
+- `src/features/` (66) — Astra Office — public API. 다음 세션에서 추가될 OfficeSnapshot presenter / schema 도 같은 entry 로 노출 예정. 현재 노출: full webview panel H
- `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) — src Chronicle Records
+- `src/docs/` (6) — Bug: Edited agent.ts Edited agent.ts Edited agent.ts Edited agent.ts Edited agent.ts ...
- `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)
@@ -81,41 +82,41 @@ flowchart LR
- `src/scaffolder/` (2) — Scaffolder template catalog. Templates are pure data — (projectName) => { [relativePath]: contents }. New templates are
**Key files**
-- `src/utils.ts` (360 lines)
+- `src/utils.ts` (408 lines)
- `src/config.ts` (298 lines)
- `src/features/company/types.ts` (446 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/core/services.ts` (164 lines)
- `src/lib/paths.ts` (151 lines)
- `src/features/company/companyConfig.ts` (896 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/sidebarProvider.ts` (4165 lines)
+- `src/sidebarProvider.ts` (4226 lines)
- `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` (536 lines) — Scoring Engine — TF-IDF + Bilingual Tokenizer 단순 includes() 키워드 매칭을 넘어서, TF-IDF 가중치 기반의 문서 스코어링을 제공합니다. 한국어/영어 양국어 토크나이저를 포함합니다.
- `src/skills/agentKnowledgeMap.ts` (374 lines)
- `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/agent.ts` (3633 lines)
+- `src/agent.ts` (3694 lines)
- `src/features/providers/types.ts` (63 lines) — Cloud LLM provider routing — model id prefix → provider id 매핑. Prefix 규칙: openrouter:anthropic/claude-3.5-sonnet → { provider: 'openrouter', model: 'anthropic/claude-3.5-sonnet' } anthropic:claude-3-5
- `src/lib/engine.ts` (906 lines)
-- `src/features/company/dispatcher.ts` (1435 lines) — 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
+- `src/retrieval/brainIndex.ts` (325 lines) — Brain Index — persistent, mtime-keyed tokenized cache of the Second Brain RAG 검색은 매 질의마다 브레인의 모든 .md 파일을 읽고 토크나이즈해서 TF-IDF 점수를 계산했습니다 — 파일 수가 많아지면 그게 병목입니다. 이 모듈은 /.astra/brain-index.json 에
+- `src/features/company/dispatcher.ts` (1437 lines) — 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
- `src/features/providers/providerConfig.ts` (78 lines) — Provider 별 API key + enable 토글 저장소. 설계: - API key 자체는 vscode.SecretStorage (secrets) 에 — settings.json / Settings Sync 침범 안 받음. - enabled 토글은 일반 settings (g1nation.providers..enabled) — 사용자가 패널에서
- `src/features/approval/approvalQueue.ts` (129 lines)
- `src/integrations/telegram/telegramClient.ts` (154 lines)
-- `src/features/astraOffice/view/runtime.ts` (1887 lines) — 자동 분리: src/sidebarProvider.ts 4002-5116 (IIFE 본문) 에서 추출. 동작 동등. ${assets.derivedBase} placeholder 는 panelHtml 에서 .replace() 로 실제 값 주입. 다음 세션에서 OfficeSnapshot 기반으로 단계적으로 잘라낼 예정.
+- `src/features/astraOffice/view/runtime.ts` (1932 lines) — 자동 분리: src/sidebarProvider.ts 4002-5116 (IIFE 본문) 에서 추출. 동작 동등. ${assets.derivedBase} placeholder 는 panelHtml 에서 .replace() 로 실제 값 주입. 다음 세션에서 OfficeSnapshot 기반으로 단계적으로 잘라낼 예정.
- `src/features/company/agents.ts` (211 lines) — 기본 에이전트 로스터 — 1인 기업 모드의 출고 디폴트. 설계 의도: 소프트웨어/게임 개발 IT 회사의 1인 기업 운영을 가정. 한 사람이 기획 → 디자인 → 개발 → QA → 출시 → 운영/마케팅을 모두 책임질 때 필요한 직군을 빠짐없이 커버하되 역할이 겹치지 않게 분리한다. 직군 구분 (혼동 방지): - 기획자(business) : 무엇을 만들지 정의
- `src/features/company/pixelOfficeState.ts` (286 lines) — Pixel Office — Agent Work Pipeline 상태를 시각화하는 UI Layer 전용 모듈. ─────────────────── 설계 원칙 ─────────────────── 1. Agent 핵심 판단 로직을 절대 바꾸지 않는다. Pipeline 진행, contract 합의, 검수 cycle, 승인 게이트 — 모두 기존 dispatcher
- `src/features/company/sessionStore.ts` (231 lines) — Disk persistence for company-mode session artefacts. Each company turn produces a timestamped directory: /.astra/company/sessions/2026-05-13T21-29/ ├─ brief.md ← CEO's task decompositio
- `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/extension.ts` (1215 lines)
-### `media/` — 6 files, ~7,243 lines
+### `media/` — 6 files, ~7,328 lines
**Key files**
-- `media/sidebar.css` (2068 lines) — Stylesheet
-- `media/sidebar.js` (3680 lines)
-- `media/sidebar.html` (546 lines) — Astra
-- `media/settings-panel.html` (328 lines) — Astra Settings
+- `media/sidebar.css` (2078 lines) — Stylesheet
+- `media/sidebar.js` (3677 lines)
+- `media/sidebar.html` (545 lines) — Astra
+- `media/settings-panel.html` (373 lines) — Astra Settings
- `media/settings-panel.css` (210 lines) — Stylesheet
-- `media/settings-panel.js` (411 lines)
+- `media/settings-panel.js` (445 lines)
### `tests/` — 35 files, ~5,969 lines
*Depends on*: `src/`
@@ -160,11 +161,12 @@ flowchart LR
- `core_py/optimizer.py` (55 lines)
- `core_py/queue_worker.py` (82 lines)
-### `docs/` — 81 files, ~3,203 lines
+### `docs/` — 85 files, ~3,294 lines
**Sub-directories**
-- `docs/records/` (68) — Astra Project Chronicle Records
-- `docs/docs/` (5) — docs Chronicle Records
+- `docs/records/` (72) — Bug: /Volumes/Data/project/Antigravity/ConnectAI 프로젝트 코드 리뷰 해줄 수 있어? 개선할 부분이 있는지, 그러고...
+- `docs/docs/` (5) — Bug: Viewed integrationretrieval.test.ts:1-59 integrationretrieval.test.ts를 통해 ...
+- `docs/Meeting/` (0)
**Key files**
- `docs/TELEGRAM_REMOTE_EXECUTION_PLAN.md` (452 lines) — Telegram Remote Execution 기획서
@@ -173,25 +175,25 @@ 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` (155 lines) — Project Timeline
+- `docs/records/ConnectAI/timeline.md` (167 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/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/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 프로젝트에만 완전히 집중하겠습니다. ...
## VS Code Extension Surface
- **Extension ID**: `g1nation.astra`
@@ -225,8 +227,13 @@ flowchart LR
- `g1nation.calendar.refresh` — Astra: Google Calendar 새로고침 📅
- `g1nation.calendar.connectOAuth` — Astra: Google Calendar OAuth 연결 (쓰기) 🔐
- `g1nation.devilAgent.toggle` — Astra: Toggle Devil Agent 🎭
-- **Configuration** (63 settings):
+- **Configuration** (68 settings):
- `g1nation.multiAgentEnabled` *(boolean)* _(default: `false`)_ — Enable Multi-Agent Workflow (Planner -> Researcher -> Writer) for complex tasks.
+ - `g1nation.datacollectBridgeUrl` *(string)* _(default: `"http://127.0.0.1:3002"`)_ — Wiki/Datacollect MCP Bridge URL. /research, /benchmark, /youtube chat slash commands route here. The Bridge must be running (`npm run bridge` in the Datacollect project).
+ - `g1nation.datacollectSavePath` *(string)* _(default: `""`)_
+ - `g1nation.datacollectCrawlDepth` *(number)* _(default: `1`)_
+ - `g1nation.datacollectMaxPages` *(number)* _(default: `8`)_
+ - `g1nation.datacollectSynthesisTemperature` *(number)* _(default: `0.1`)_
- `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.memoryMediumTermSessions` *(number)* _(default: `5`)_ — Number of recent saved chat sessions included as medium-term memory.
@@ -271,7 +278,7 @@ flowchart LR
- `g1nation.company.autoSelectPipeline` *(boolean)* _(default: `true`)_ — Let the intent classifier *automatically switch* to the pipeline it recommends for this turn (e.g. short '기획서까지만' for a planning ask, full '풀 프로덕트' for an end-to-end product). Your explicitly-activate
- `g1nation.company.intentAlignmentMode` *(string)* _(default: `"smart"`)_ — Intent Alignment — turn user prompts into an explicit Requirement Contract (C-G-C-F-Q) before dispatching a pipeline. 'off' = legacy, pipeline runs immediately. 'smart' (default) = run when confidence
- `g1nation.company.intentAlignmentMaxRounds` *(number)* _(default: `3`)_ — Maximum back-and-forth rounds the Intent Alignment analyzer is allowed to ask before forcing a 'confirm or cancel' card (it stops asking new questions and shows the current contract for user approval)
- - `g1nation.selfReflector.enabled` *(boolean)* _(default: `true`)_ — Self-Reflector Phase A — append a [Self-Reflector Check] block at the end of every substantive LLM answer (Consistency / Completeness / Accuracy, plus References / Paths for code answers). Zero extra
+ - `g1nation.selfReflector.enabled` *(boolean)* _(default: `false`)_ — Self-Reflector Phase A — append a [Self-Reflector Check] block at the end of every substantive LLM answer (Consistency / Completeness / Accuracy, plus References / Paths for code answers). Zero extra
- `g1nation.selfReflector.externalVerification` *(boolean)* _(default: `false`)_ — Self-Reflector Phase B — after every 1인 기업 specialist response, run a *separate* LLM call to verify the output from an outside-context perspective (catches the 'same model self-validates' blind spot).
- `g1nation.selfReflector.executionVerification` *(boolean)* _(default: `false`)_ — Self-Reflector Phase C — after a code file is created via , automatically run the language's syntax check (Python: py_compile, JS: node --check, TS: project tsc --noEmit). Failures are su
- `g1nation.company.pixelOffice.enabled` *(boolean)* _(default: `true`)_ — Show the Pixel Office visualisation panel above the chat — a small pixel-office-style display that mirrors the agent's current pipeline status (analyzing, need_clarification, executing, reviewing, wai
@@ -281,12 +288,7 @@ flowchart LR
- `g1nation.google.calendarId` *(string)* _(default: `"primary"`)_
- `g1nation.google.defaultEventDurationMinutes` *(number)* _(default: `60`)_ — end / duration 둘 다 없는 일정의 기본 길이 (분). agent 가 회의록에서 시각만 추출하고 종료 시각은 명시 안 했을 때 적용.
- `g1nation.google.icalUrl` *(string)* _(default: `""`)_
- - `g1nation.google.icalDaysAhead` *(number)* _(default: `14`)_ — iCal 캐시에 포함할 다가오는 일정 기간 (일). default 14 = 2주치.
- - `g1nation.providers.openrouter.enabled` *(boolean)* _(default: `false`)_ — OpenRouter cloud provider 활성화 — Claude/Gemini/GPT 등 100+ 모델을 OpenAI 호환 API 로 사용. API key 는 Astra Settings 패널에서 등록 (Secret Storage 사용, settings.json 비저장).
- - `g1nation.providers.openrouter.defaultModel` *(string)* _(default: `""`)_ — OpenRouter 의 기본 모델 (예: 'anthropic/claude-3.5-sonnet'). 모델 선택 시 'openrouter:' 형식으로 사이드바 dropdown 에 표시.
- - `g1nation.providers.anthropic.enabled` *(boolean)* _(default: `false`)_ — Anthropic Claude 직접 API 활성화. OpenRouter 보다 마진 적고 prompt caching 등 native 기능 사용 가능. API key 는 Secret Storage.
- - `g1nation.providers.anthropic.defaultModel` *(string)* _(default: `"claude-3-5-sonnet-20241022"`)_ — Anthropic 의 기본 모델. 예: 'claude-3-5-sonnet-20241022', 'claude-3-5-haiku-20241022'.
- - _…and 3 more_
+ - _…and 8 more_
## Dependencies
- **Runtime** (2): `@lmstudio/sdk`, `pdf-parse`
@@ -334,7 +336,7 @@ Astra는 대표님의 명시적인 승인 하에 로컬 시스템의 강력한
**Designed for High-Performance Decision Making.**
Copyright (C) **g1nation**. All rights reserved.
-_Last auto-scan: 2026-05-17T14:50:50.535Z · signature `5421df2d`_
+_Last auto-scan: 2026-05-22T06:00:02.986Z · signature `3e9af639`_
## Purpose
diff --git a/.astra/project-context/scan-cache.json b/.astra/project-context/scan-cache.json
index 9de3882..02c51df 100644
--- a/.astra/project-context/scan-cache.json
+++ b/.astra/project-context/scan-cache.json
@@ -1,11 +1,11 @@
{
"version": 1,
- "generatedAt": "2026-05-17T14:50:50.547Z",
+ "generatedAt": "2026-05-22T06:00:03.020Z",
"files": {
"src/agent.ts": {
- "mtimeMs": 1778943938000,
- "size": 209036,
- "lines": 3633,
+ "mtimeMs": 1779428598292.2295,
+ "size": 216127,
+ "lines": 3694,
"role": "",
"imports": [
"src/utils",
@@ -39,8 +39,8 @@
]
},
"src/agents/AgentWorkflowManager.ts": {
- "mtimeMs": 1778690404000,
- "size": 2262,
+ "mtimeMs": 1778720117490.4294,
+ "size": 2322,
"lines": 60,
"role": "",
"imports": [
@@ -50,8 +50,8 @@
]
},
"src/agents/factory.ts": {
- "mtimeMs": 1778690336000,
- "size": 11023,
+ "mtimeMs": 1778720117507.1616,
+ "size": 11242,
"lines": 219,
"role": "",
"imports": [
@@ -60,8 +60,8 @@
]
},
"src/agents/reflectionPersister.ts": {
- "mtimeMs": 1778763469000,
- "size": 11986,
+ "mtimeMs": 1778807413489.8743,
+ "size": 12294,
"lines": 308,
"role": "Reflection → Lesson persistence Take the Reflector agent's structured critique and persist any substantive findings as a lesson card in /lessons/auto-reflector/. The existing brain retrieval",
"imports": [
@@ -70,9 +70,9 @@
]
},
"src/bridge.ts": {
- "mtimeMs": 1778681774000,
- "size": 9705,
- "lines": 227,
+ "mtimeMs": 1779411812096.6685,
+ "size": 10768,
+ "lines": 242,
"role": "",
"imports": [
"src/utils",
@@ -83,21 +83,21 @@
]
},
"src/config.ts": {
- "mtimeMs": 1778902489000,
- "size": 14623,
+ "mtimeMs": 1779268787168.0276,
+ "size": 14922,
"lines": 298,
"role": "",
"imports": []
},
"src/core/astraPath.ts": {
- "mtimeMs": 1778169995000,
- "size": 1782,
+ "mtimeMs": 1778037123135.2776,
+ "size": 1832,
"lines": 50,
"role": "Astra Path Resolver (경로 해결기) Astra의 모든 데이터 파일(.astra 디렉토리)의 경로를 중앙에서 관리합니다. 확장 프로그램의 설치 경로(extensionUri) 기반으로 .astra 디렉토리를 해결하여, 사용자 프로젝트 루트가 아닌 ConnectAI 패키지 내부에 데이터를 저장합니다. 이 모듈은 AAL(Astra Autonomou",
"imports": []
},
"src/core/conflict.ts": {
- "mtimeMs": 1778169995000,
+ "mtimeMs": 1778038174478.8147,
"size": 1726,
"lines": 30,
"role": "",
@@ -106,35 +106,35 @@
]
},
"src/core/dataProcessor.ts": {
- "mtimeMs": 1778169995000,
+ "mtimeMs": 1778038193232.0127,
"size": 3235,
"lines": 96,
"role": "Aggregate result type definition",
"imports": []
},
"src/core/errorHandler.ts": {
- "mtimeMs": 1777808065000,
- "size": 2305,
+ "mtimeMs": 1777511752606.2458,
+ "size": 2354,
"lines": 49,
"role": "",
"imports": []
},
"src/core/errors.ts": {
- "mtimeMs": 1778169995000,
- "size": 924,
+ "mtimeMs": 1778037081022.028,
+ "size": 958,
"lines": 34,
"role": "g1nation Custom Error Classes",
"imports": []
},
"src/core/events.ts": {
- "mtimeMs": 1777808065000,
- "size": 993,
+ "mtimeMs": 1778028987396.9893,
+ "size": 1028,
"lines": 35,
"role": "",
"imports": []
},
"src/core/health.ts": {
- "mtimeMs": 1778169995000,
+ "mtimeMs": 1778038139567.3984,
"size": 2873,
"lines": 79,
"role": "",
@@ -144,7 +144,7 @@
]
},
"src/core/lock.ts": {
- "mtimeMs": 1778169995000,
+ "mtimeMs": 1778038157826.973,
"size": 2358,
"lines": 66,
"role": "",
@@ -153,8 +153,8 @@
]
},
"src/core/queue.ts": {
- "mtimeMs": 1778674336000,
- "size": 2428,
+ "mtimeMs": 1778666871393.5244,
+ "size": 2509,
"lines": 81,
"role": "",
"imports": [
@@ -162,8 +162,8 @@
]
},
"src/core/responseRecovery.ts": {
- "mtimeMs": 1778598587000,
- "size": 12304,
+ "mtimeMs": 1778664139958.9634,
+ "size": 12529,
"lines": 225,
"role": "Response Recovery — Thought Quarantine + Final-only Retry + Auto-Continuation The user already asked their question; they're waiting for an answer, not for a chance to babysit the generation engine. S",
"imports": [
@@ -171,8 +171,8 @@
]
},
"src/core/services.ts": {
- "mtimeMs": 1778421200000,
- "size": 6692,
+ "mtimeMs": 1778549008895.9155,
+ "size": 6856,
"lines": 164,
"role": "",
"imports": [
@@ -181,8 +181,8 @@
]
},
"src/core/session.ts": {
- "mtimeMs": 1777808065000,
- "size": 2785,
+ "mtimeMs": 1777511752609.8882,
+ "size": 2873,
"lines": 88,
"role": "",
"imports": [
@@ -191,14 +191,14 @@
]
},
"src/core/statusBar.ts": {
- "mtimeMs": 1777808065000,
- "size": 2000,
+ "mtimeMs": 1778028987401.3042,
+ "size": 2057,
"lines": 57,
"role": "",
"imports": []
},
"src/core/telemetry.ts": {
- "mtimeMs": 1778674336000,
+ "mtimeMs": 1778666901466.1726,
"size": 5442,
"lines": 129,
"role": "Telemetry — append-only usage events to .astra/usage.jsonl Why local-file telemetry instead of a webview dashboard or remote endpoint: - Astra is local-first. No data leaves the machine. - JSONL is tr",
@@ -208,8 +208,8 @@
]
},
"src/core/transaction.ts": {
- "mtimeMs": 1778251556000,
- "size": 4458,
+ "mtimeMs": 1778549008897.4194,
+ "size": 4590,
"lines": 132,
"role": "",
"imports": [
@@ -217,52 +217,52 @@
"src/utils"
]
},
- "src/docs/records/src/README.md": {
- "mtimeMs": 1777949473000,
- "size": 422,
- "lines": 18,
- "role": "src Chronicle Records",
- "imports": []
- },
"src/docs/records/src/bugs/BUG-0001-edited-agent-ts-edited-agent-ts-edited-agent-ts-edited-agent.md": {
- "mtimeMs": 1777949473000,
- "size": 1797,
+ "mtimeMs": 1778028987403.465,
+ "size": 1813,
"lines": 16,
"role": "Bug: Edited agent.ts Edited agent.ts Edited agent.ts Edited agent.ts Edited agent.ts ...",
"imports": []
},
- "src/docs/records/src/bugs/BUG-0002-viewed-agent-ts-2159-2206-제공해주신-세부-파일-구조와-지식-수집-워크플로우-관점의-코드.md": {
- "mtimeMs": 1777949638000,
- "size": 2201,
+ "src/docs/records/src/bugs/BUG-0002-viewed-agent-ts-2159-2206-제공해주신-세부-파일-구조와-지식-수집-워크플로우-관점의-코드.md": {
+ "mtimeMs": 1778028987403.9697,
+ "size": 2217,
"lines": 16,
"role": "Bug: Viewed agent.ts:2159-2206 제공해주신 세부 파일 구조와 지식 수집 워크플로우 관점의 코드리뷰 요청을 정독했습니다. 이...",
"imports": []
},
"src/docs/records/src/chronicle.config.json": {
- "mtimeMs": 1777949638000,
- "size": 517,
+ "mtimeMs": 1778028987403.9697,
+ "size": 528,
"lines": 11,
"role": "JSON configuration",
"imports": []
},
"src/docs/records/src/project-profile.md": {
- "mtimeMs": 1777949473000,
- "size": 582,
+ "mtimeMs": 1778028987404.973,
+ "size": 613,
"lines": 31,
"role": "Project Profile",
"imports": []
},
+ "src/docs/records/src/README.md": {
+ "mtimeMs": 1778028987402.338,
+ "size": 440,
+ "lines": 18,
+ "role": "src Chronicle Records",
+ "imports": []
+ },
"src/docs/records/src/timeline.md": {
- "mtimeMs": 1777949638000,
- "size": 381,
+ "mtimeMs": 1778028987405.4775,
+ "size": 391,
"lines": 10,
"role": "Project Timeline",
"imports": []
},
"src/extension.ts": {
- "mtimeMs": 1778943661000,
- "size": 63135,
- "lines": 1215,
+ "mtimeMs": 1779411729280.646,
+ "size": 65966,
+ "lines": 1233,
"role": "",
"imports": [
"src/utils",
@@ -297,8 +297,8 @@
]
},
"src/features/approval/approvalPanelProvider.ts": {
- "mtimeMs": 1778674336000,
- "size": 7132,
+ "mtimeMs": 1778664480470.9922,
+ "size": 7285,
"lines": 153,
"role": "",
"imports": [
@@ -307,8 +307,8 @@
]
},
"src/features/approval/approvalQueue.ts": {
- "mtimeMs": 1778251548000,
- "size": 4722,
+ "mtimeMs": 1778549008899.4456,
+ "size": 4851,
"lines": 129,
"role": "",
"imports": [
@@ -316,8 +316,8 @@
]
},
"src/features/approval/approvalStatusBar.ts": {
- "mtimeMs": 1778251623000,
- "size": 1601,
+ "mtimeMs": 1778549008899.4456,
+ "size": 1642,
"lines": 41,
"role": "",
"imports": [
@@ -325,8 +325,8 @@
]
},
"src/features/astraOffice/index.ts": {
- "mtimeMs": 1778931477000,
- "size": 789,
+ "mtimeMs": 1779065453862.6475,
+ "size": 807,
"lines": 18,
"role": "Astra Office — public API. 다음 세션에서 추가될 OfficeSnapshot presenter / schema 도 같은 entry 로 노출 예정. 현재 노출: full webview panel HTML 생성 함수. sidebarProvider.ts 는 이 한 줄만 import.",
"imports": [
@@ -337,8 +337,8 @@
]
},
"src/features/astraOffice/presenter.ts": {
- "mtimeMs": 1778932441000,
- "size": 7368,
+ "mtimeMs": 1779065453862.6475,
+ "size": 7549,
"lines": 181,
"role": "Presenter — 옛 AgentWorkState + bubble queue + activity items 를 OfficeSnapshot 으로 변환하는 pure 함수. mini / full view 둘 다 같은 OfficeSnapshot 을 받게 만드는 게 목표. 이번 세션의 범위: 인터페이스 + 스텁. 실제 wiring 은 다음 세션에서: - sideb",
"imports": [
@@ -348,8 +348,8 @@
]
},
"src/features/astraOffice/schema.ts": {
- "mtimeMs": 1778931632000,
- "size": 10631,
+ "mtimeMs": 1779065453864.1523,
+ "size": 10936,
"lines": 305,
"role": "OfficeSnapshot — Astra Office 의 도메인 타입. 동시성 진실 (docs/ASTRAOFFICEREFACTOR.md §1): dispatcher 는 직렬이라 한 시점에 active agent 는 0 또는 1명. 이걸 데이터로 강제하는 게 이 타입의 핵심 역할. 이 세션에서는 타입 + validator + empty factory 만. 백",
"imports": [
@@ -357,29 +357,29 @@
]
},
"src/features/astraOffice/view/layoutSchema.ts": {
- "mtimeMs": 1778931707000,
- "size": 6475,
+ "mtimeMs": 1779065453864.8176,
+ "size": 6655,
"lines": 180,
"role": "Pixel Office layout 저장 스키마 — workspaceState 의 g1nation.pixelOfficeLayout 키 에 저장되는 객체의 런타임 validator + v1 → v2 migration. 옛 runtime.ts 의 isV2Snap() heuristic 을 정식 schema 로 격상. webview 에서 받는 즉시 한 번 통과시키",
"imports": []
},
"src/features/astraOffice/view/officeBody.ts": {
- "mtimeMs": 1778938908000,
- "size": 4112,
+ "mtimeMs": 1779065453865.8494,
+ "size": 4207,
"lines": 103,
"role": "",
"imports": []
},
"src/features/astraOffice/view/officeStyles.ts": {
- "mtimeMs": 1778942662000,
- "size": 25747,
+ "mtimeMs": 1779065453866.8667,
+ "size": 26165,
"lines": 419,
"role": "",
"imports": []
},
"src/features/astraOffice/view/panelHtml.ts": {
- "mtimeMs": 1778937313000,
- "size": 923,
+ "mtimeMs": 1779065453867.871,
+ "size": 949,
"lines": 26,
"role": "Full Astra Office webview HTML composition. 옛 sidebarProvider.ts 의 거대한 pixelOfficePanelHtml 을 4개 파일로 분리한 entry. 이번 세션은 동작 동등 분리 만. 다음 세션에 mini view 와 공통 presenter 도입.",
"imports": [
@@ -389,15 +389,15 @@
]
},
"src/features/astraOffice/view/runtime.ts": {
- "mtimeMs": 1779028539000,
- "size": 90525,
- "lines": 1887,
+ "mtimeMs": 1779411798626.195,
+ "size": 93940,
+ "lines": 1932,
"role": "자동 분리: src/sidebarProvider.ts 4002-5116 (IIFE 본문) 에서 추출. 동작 동등. ${assets.derivedBase} placeholder 는 panelHtml 에서 .replace() 로 실제 값 주입. 다음 세션에서 OfficeSnapshot 기반으로 단계적으로 잘라낼 예정.",
"imports": []
},
"src/features/calendar/calendarApi.ts": {
- "mtimeMs": 1778935879000,
- "size": 8782,
+ "mtimeMs": 1779065453869.39,
+ "size": 8987,
"lines": 205,
"role": "Google Calendar API v3 — event create/list 호출. access token 은 caller 가 직접 주입한다. 만료 처리는 withFreshAccessToken 헬퍼가 refresh token 으로 갱신 → 호출 → 401 발생 시 한 번 더 갱신 + 재시도. 외부 라이브러리(googleapis) 안 씀 — Calendar ",
"imports": [
@@ -406,8 +406,8 @@
]
},
"src/features/calendar/calendarCache.ts": {
- "mtimeMs": 1778937433000,
- "size": 11824,
+ "mtimeMs": 1779065453870.9949,
+ "size": 12065,
"lines": 241,
"role": "Google Calendar (iCal) 캐시 — fetch + parse + 회사 shared/calendarcache.md 에 저장. Connectorigin 의 googlecalendar.py 를 TypeScript / native fetch 로 옮김. OAuth 없음. 사용자가 Google Calendar 설정 → \"비공개 주소(iCal 형식)\" 복",
"imports": [
@@ -415,15 +415,15 @@
]
},
"src/features/calendar/icsParser.ts": {
- "mtimeMs": 1778934638000,
- "size": 4823,
+ "mtimeMs": 1779065453870.9949,
+ "size": 4937,
"lines": 114,
"role": "Minimal ICS parser — no library deps. Connectorigin 의 Python 버전을 그대로 옮겼고, 본 함수는 pure 라서 단위테스트가 쉽다. 처리 범위: - VEVENT 블록 추출 - line continuation (다음 줄이 공백 시작) 펼치기 - SUMMARY / DESCRIPTION / LOCATION / DTST",
"imports": []
},
"src/features/calendar/index.ts": {
- "mtimeMs": 1778935400000,
- "size": 561,
+ "mtimeMs": 1779065453871.9966,
+ "size": 593,
"lines": 32,
"role": "",
"imports": [
@@ -434,15 +434,15 @@
]
},
"src/features/calendar/oauth.ts": {
- "mtimeMs": 1778935851000,
- "size": 10705,
+ "mtimeMs": 1779065453873.0256,
+ "size": 10940,
"lines": 235,
"role": "Google OAuth 2.0 — loopback (Desktop app) 흐름. Google 은 Desktop 앱 OAuth client 에 대해 http://127.0.0.1: redirect URI 를 허용한다. 본 모듈은: 1. ephemeral port 에 일회용 HTTP 서버 띄움 2. 사용자 브라우저로 Google 로",
"imports": []
},
"src/features/company/agents.ts": {
- "mtimeMs": 1778936611000,
- "size": 15031,
+ "mtimeMs": 1779065453874.572,
+ "size": 15242,
"lines": 211,
"role": "기본 에이전트 로스터 — 1인 기업 모드의 출고 디폴트. 설계 의도: 소프트웨어/게임 개발 IT 회사의 1인 기업 운영을 가정. 한 사람이 기획 → 디자인 → 개발 → QA → 출시 → 운영/마케팅을 모두 책임질 때 필요한 직군을 빠짐없이 커버하되 역할이 겹치지 않게 분리한다. 직군 구분 (혼동 방지): - 기획자(business) : 무엇을 만들지 정의 ",
"imports": [
@@ -450,8 +450,8 @@
]
},
"src/features/company/ceoPlanner.ts": {
- "mtimeMs": 1778902489000,
- "size": 11781,
+ "mtimeMs": 1778814432469.254,
+ "size": 12050,
"lines": 269,
"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": [
@@ -464,8 +464,8 @@
]
},
"src/features/company/ceoReporter.ts": {
- "mtimeMs": 1778762677000,
- "size": 4895,
+ "mtimeMs": 1778739926808.2551,
+ "size": 5017,
"lines": 122,
"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": [
@@ -477,8 +477,8 @@
]
},
"src/features/company/companyConfig.ts": {
- "mtimeMs": 1778902489000,
- "size": 40139,
+ "mtimeMs": 1778811673797.1216,
+ "size": 41035,
"lines": 896,
"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": [
@@ -487,9 +487,9 @@
]
},
"src/features/company/dispatcher.ts": {
- "mtimeMs": 1778936524000,
- "size": 73113,
- "lines": 1435,
+ "mtimeMs": 1779065453875.0962,
+ "size": 74549,
+ "lines": 1437,
"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",
@@ -515,8 +515,8 @@
]
},
"src/features/company/index.ts": {
- "mtimeMs": 1778902489000,
- "size": 2596,
+ "mtimeMs": 1778814836698.1172,
+ "size": 2702,
"lines": 106,
"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": [
@@ -533,7 +533,7 @@
]
},
"src/features/company/intentAlignment.ts": {
- "mtimeMs": 1778902489000,
+ "mtimeMs": 1778813958976.1824,
"size": 15285,
"lines": 334,
"role": "Intent Alignment — 사용자의 자연어 요청을 실행 가능한 작업 조건으로 변환. 사용자는 자기 의도와 배경지식이 에이전트에게 충분히 전달되었다고 착각하는 경향이 있다 (투명성의 착각·지식의 저주·공통 기반 부족). 그래서 에이전트가 즉시 작업에 돌입하면 사용자가 머릿속에 가진 것과 다른 결과를 만들어 낸다. 이 모듈은 그 격차를 메꾸는 한 단계 ",
@@ -544,7 +544,7 @@
]
},
"src/features/company/intentClassifier.ts": {
- "mtimeMs": 1778902489000,
+ "mtimeMs": 1778819562785.657,
"size": 17372,
"lines": 348,
"role": "Intent classifier for 1인 기업 모드 chat input. The company mode used to route every chat message through the full dispatcher (CEO planner → specialists → CEO synthesis). That meant casual messages like \"고",
@@ -554,8 +554,8 @@
]
},
"src/features/company/pipelineTemplates.ts": {
- "mtimeMs": 1778933936000,
- "size": 15125,
+ "mtimeMs": 1779065453876.108,
+ "size": 15403,
"lines": 278,
"role": "Built-in pipeline templates for 1인 기업 모드. These are blueprints, not data — they're surfaced in the manage panel's \"템플릿에서 추가\" dropdown so a non-developer user can stamp out a working pipeline in one cl",
"imports": [
@@ -563,22 +563,22 @@
]
},
"src/features/company/pixelOfficeState.ts": {
- "mtimeMs": 1778902489000,
+ "mtimeMs": 1778843402595.067,
"size": 10025,
"lines": 286,
"role": "Pixel Office — Agent Work Pipeline 상태를 시각화하는 UI Layer 전용 모듈. ─────────────────── 설계 원칙 ─────────────────── 1. Agent 핵심 판단 로직을 절대 바꾸지 않는다. Pipeline 진행, contract 합의, 검수 cycle, 승인 게이트 — 모두 기존 dispatcher ",
"imports": []
},
"src/features/company/promptAssets.ts": {
- "mtimeMs": 1778680887000,
- "size": 6782,
+ "mtimeMs": 1778720117525.2087,
+ "size": 6896,
"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": 1778936588000,
- "size": 18723,
+ "mtimeMs": 1779065453877.1128,
+ "size": 19037,
"lines": 314,
"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 (, ",
"imports": [
@@ -590,29 +590,29 @@
]
},
"src/features/company/prompts/ceo-chat.md": {
- "mtimeMs": 1778680831000,
- "size": 462,
+ "mtimeMs": 1778720117527.2378,
+ "size": 466,
"lines": 4,
"role": "당신은 {{COMPANY}}의 CEO입니다. 사용자(사장님)와 짧게 인사·안부·잡담을 주고받습니다. - 한국어로 1~3문장. 친근하지만 사장-CEO 관계는 유지. - 인사·안부 질문이면 자연스럽게 응답하세요. 작업 지시가 아니면 굳이 작업 분배 제안 X. - 회사 정체성·최근 결정·추적기 상태가 컨텍스트에 있으면 자연스럽게 활용. - JSON 출력 금지. ",
"imports": []
},
"src/features/company/prompts/ceo-planner.md": {
- "mtimeMs": 1778680831000,
- "size": 3199,
+ "mtimeMs": 1778720117527.2378,
+ "size": 3237,
"lines": 38,
"role": "당신은 \"{{COMPANY}}\"의 CEO입니다. 1인 AI 기업의 사령관이자 오케스트레이터입니다.",
"imports": []
},
"src/features/company/prompts/ceo-report.md": {
- "mtimeMs": 1778680831000,
- "size": 1373,
+ "mtimeMs": 1778720117528.7502,
+ "size": 1394,
"lines": 21,
"role": "당신은 {{COMPANY}}의 CEO입니다. 방금 팀이 작업을 끝냈습니다. 각 에이전트의 산출물을 읽고 사장님께 올릴 종합 보고서를 작성하세요.",
"imports": []
},
"src/features/company/resumeStore.ts": {
- "mtimeMs": 1778768128000,
- "size": 5672,
+ "mtimeMs": 1778807413496.3787,
+ "size": 5806,
"lines": 134,
"role": "Disk persistence for company-turn resume state. 각 turn의 sessionDir 안에 resume.json을 두고, dispatcher가 매 의미 있는 시점(plan 확정 / 각 stage 직후 / abort 시점)에 현재 상태를 덮어쓴다. 재개 시점에는 이 파일을 읽어 nextIndex 부터 dispatch 재개. ",
"imports": [
@@ -622,8 +622,8 @@
]
},
"src/features/company/sessionStore.ts": {
- "mtimeMs": 1778680971000,
- "size": 8727,
+ "mtimeMs": 1778720117528.7502,
+ "size": 8958,
"lines": 231,
"role": "Disk persistence for company-mode session artefacts. Each company turn produces a timestamped directory: /.astra/company/sessions/2026-05-13T21-29/ ├─ brief.md ← CEO's task decompositio",
"imports": [
@@ -632,8 +632,8 @@
]
},
"src/features/company/telegramReport.ts": {
- "mtimeMs": 1778762677000,
- "size": 8126,
+ "mtimeMs": 1778739949327.3745,
+ "size": 8294,
"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": [
@@ -645,22 +645,40 @@
]
},
"src/features/company/types.ts": {
- "mtimeMs": 1778902489000,
- "size": 20877,
+ "mtimeMs": 1778813870251.361,
+ "size": 21323,
"lines": 446,
"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/datacollect/bridgeClient.ts": {
+ "mtimeMs": 1779174431038.135,
+ "size": 3518,
+ "lines": 86,
+ "role": "",
+ "imports": []
+ },
+ "src/features/datacollect/slashRouter.ts": {
+ "mtimeMs": 1779343360530.8965,
+ "size": 73170,
+ "lines": 1413,
+ "role": "",
+ "imports": [
+ "src/utils",
+ "src/features/datacollect/bridgeClient",
+ "src/features/calendar"
+ ]
+ },
"src/features/devilAgent/devilPrompt.ts": {
- "mtimeMs": 1778943576000,
- "size": 3591,
+ "mtimeMs": 1779065453878.1177,
+ "size": 3662,
"lines": 71,
"role": "Devil's Advocate (도현) — system prompt 빌더. 설계 원칙: - 모든 약점을 나열하지 않음. 한 turn 에 1개 — 사용자가 깊게 생각하게. - 'X 입장에서 본다면' framing — 본인 의견이 아니라 다른 시점 으로 제시. 이는 LLM 의 '내가 옳다' 경향을 줄이는 잘 알려진 패턴. - 통계 / 구체 수치 / 외부 사례 ",
"imports": []
},
"src/features/devilAgent/devilService.ts": {
- "mtimeMs": 1778943601000,
- "size": 2457,
+ "mtimeMs": 1779065453879.116,
+ "size": 2517,
"lines": 60,
"role": "Devil Agent — 직전 답변에 대한 반박 생성기. 동작: 1. agent.ts 가 main turn 완료 직후 호출 2. 같은 model/engine 으로 별도 LLM call 1회 — 짧은 비판 한 문단 생성 3. 결과를 webview 로 'devilRebuttal' message 로 send 4. 실패 / 비활성 시 silent skip — ma",
"imports": [
@@ -668,8 +686,8 @@
]
},
"src/features/devilAgent/index.ts": {
- "mtimeMs": 1778943609000,
- "size": 263,
+ "mtimeMs": 1779065453879.116,
+ "size": 276,
"lines": 13,
"role": "",
"imports": [
@@ -678,8 +696,8 @@
]
},
"src/features/projectArchitecture/index.ts": {
- "mtimeMs": 1778691699000,
- "size": 25373,
+ "mtimeMs": 1778720117531.2734,
+ "size": 25946,
"lines": 573,
"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": [
@@ -689,15 +707,15 @@
]
},
"src/features/projectArchitecture/intentDetector.ts": {
- "mtimeMs": 1778676956000,
- "size": 6170,
+ "mtimeMs": 1778720117532.2788,
+ "size": 6318,
"lines": 148,
"role": "Project-intent detection from a chat message. Goal: when the user says \"나 ConnectAI 프로젝트 진행할 거야\" (or similar), spot the intent + project handle so the sidebar can activate Project Mode and auto-attach",
"imports": []
},
"src/features/projectArchitecture/mermaid.ts": {
- "mtimeMs": 1778678215000,
- "size": 2699,
+ "mtimeMs": 1778720117533.2854,
+ "size": 2768,
"lines": 69,
"role": "Mermaid diagram renderers for the architecture doc. Two diagrams: a directory mindmap so the user can see the shape of the project at a glance, and a flowchart that shows which top-level module import",
"imports": [
@@ -705,8 +723,8 @@
]
},
"src/features/projectArchitecture/scanner.ts": {
- "mtimeMs": 1778678939000,
- "size": 28299,
+ "mtimeMs": 1778720117534.286,
+ "size": 28943,
"lines": 644,
"role": "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",
"imports": [
@@ -716,8 +734,8 @@
]
},
"src/features/projectChronicle/guardPrompt.ts": {
- "mtimeMs": 1777870211000,
- "size": 6880,
+ "mtimeMs": 1778028987407.7454,
+ "size": 6955,
"lines": 75,
"role": "",
"imports": [
@@ -725,8 +743,8 @@
]
},
"src/features/projectChronicle/index.ts": {
- "mtimeMs": 1777808065000,
- "size": 7490,
+ "mtimeMs": 1778028987408.4517,
+ "size": 7679,
"lines": 189,
"role": "",
"imports": [
@@ -737,15 +755,15 @@
]
},
"src/features/projectChronicle/markdownFileWriter.ts": {
- "mtimeMs": 1777808065000,
- "size": 1317,
+ "mtimeMs": 1778028987409.2556,
+ "size": 1358,
"lines": 41,
"role": "",
"imports": []
},
"src/features/projectChronicle/templates.ts": {
- "mtimeMs": 1777808065000,
- "size": 6699,
+ "mtimeMs": 1778028987409.766,
+ "size": 6957,
"lines": 258,
"role": "",
"imports": [
@@ -753,15 +771,15 @@
]
},
"src/features/projectChronicle/types.ts": {
- "mtimeMs": 1778676848000,
- "size": 3129,
+ "mtimeMs": 1778720117534.7898,
+ "size": 3247,
"lines": 118,
"role": "",
"imports": []
},
"src/features/providers/anthropic.ts": {
- "mtimeMs": 1778941456000,
- "size": 4111,
+ "mtimeMs": 1779065453880.645,
+ "size": 4219,
"lines": 108,
"role": "Anthropic Messages API adapter. 차이점 (OpenAI 와): 1. base URL: https://api.anthropic.com/v1 2. 인증: x-api-key: + anthropic-version: 2023-06-01 3. system prompt 는 messages 가 아니라 top-level system 필드 ",
"imports": [
@@ -771,8 +789,8 @@
]
},
"src/features/providers/gemini.ts": {
- "mtimeMs": 1778941478000,
- "size": 4326,
+ "mtimeMs": 1779065453881.3628,
+ "size": 4434,
"lines": 108,
"role": "Google Gemini Generative Language API adapter. 차이점 (OpenAI 와): 1. base URL: https://generativelanguage.googleapis.com/v1beta 2. 인증: ?key= (query parameter) 3. 메시지 형식: contents: [{role: 'user'",
"imports": [
@@ -782,8 +800,8 @@
]
},
"src/features/providers/index.ts": {
- "mtimeMs": 1778941521000,
- "size": 3242,
+ "mtimeMs": 1779065453882.3787,
+ "size": 3311,
"lines": 69,
"role": "Cloud LLM provider public API. 일반 호출 흐름: 1. agent.ts 의 chat 진입부에서 parseModelPrefix(modelId) 호출 2. null → local engine 경로 (옛 로직). 객체 → streamCloudCompletion(context, hit, params) 호출 3. Response 의 body ",
"imports": [
@@ -795,8 +813,8 @@
]
},
"src/features/providers/openrouter.ts": {
- "mtimeMs": 1778941431000,
- "size": 2673,
+ "mtimeMs": 1779065453882.3787,
+ "size": 2748,
"lines": 75,
"role": "OpenRouter — OpenAI 호환 API. 별도 transform 없이 fetch Response 를 그대로 반환. Base: https://openrouter.ai/api/v1 POST /chat/completions — OpenAI 형식 그대로. stream:true 면 SSE. GET /models — 사용 가능 모델 목록. 인증: Author",
"imports": [
@@ -805,8 +823,8 @@
]
},
"src/features/providers/providerConfig.ts": {
- "mtimeMs": 1778941498000,
- "size": 2683,
+ "mtimeMs": 1779065453883.386,
+ "size": 2761,
"lines": 78,
"role": "Provider 별 API key + enable 토글 저장소. 설계: - API key 자체는 vscode.SecretStorage (secrets) 에 — settings.json / Settings Sync 침범 안 받음. - enabled 토글은 일반 settings (g1nation.providers..enabled) — 사용자가 패널에서 ",
"imports": [
@@ -814,23 +832,23 @@
]
},
"src/features/providers/streamHelpers.ts": {
- "mtimeMs": 1778941413000,
- "size": 5904,
+ "mtimeMs": 1779065453883.386,
+ "size": 6048,
"lines": 144,
"role": "Stream transformer — provider 별 SSE 형식을 OpenAI 호환 SSE 로 변환. 이렇게 하면 agent.ts 의 기존 SSE 파서 (data: {...delta...} 형식 가정) 가 변경 없이 모든 provider 출력을 같은 코드 경로로 소비할 수 있다. 신규 provider 가 들어와도 adapter 하나만 추가하면 됨 (c",
"imports": []
},
"src/features/providers/types.ts": {
- "mtimeMs": 1778941377000,
- "size": 2370,
+ "mtimeMs": 1779065453884.8909,
+ "size": 2433,
"lines": 63,
"role": "Cloud LLM provider routing — model id prefix → provider id 매핑. Prefix 규칙: openrouter:anthropic/claude-3.5-sonnet → { provider: 'openrouter', model: 'anthropic/claude-3.5-sonnet' } anthropic:claude-3-5",
"imports": []
},
"src/features/secondBrainTrace.ts": {
- "mtimeMs": 1778248166000,
- "size": 37475,
- "lines": 760,
+ "mtimeMs": 1779411561816.5603,
+ "size": 39429,
+ "lines": 792,
"role": "",
"imports": [
"src/utils",
@@ -838,30 +856,30 @@
]
},
"src/features/selfReflector/selfReflectorExecution.ts": {
- "mtimeMs": 1778902489000,
- "size": 7758,
- "lines": 172,
+ "mtimeMs": 1779325350825.2378,
+ "size": 9570,
+ "lines": 207,
"role": "Self-Reflector Phase C — 실행 기반 검증. Phase A/B는 LLM 텍스트 분석에 의존하므로 \"코드가 실제로 컴파일되는가?\" 같은 질문엔 한계가 있다. Phase C는 정답: 그냥 실행해 본다. 동작: 1. action-tag executor가 반환한 report를 받아 ✅ Created: / ✅ Edited: ",
"imports": [
"src/utils"
]
},
"src/features/selfReflector/selfReflectorHollow.ts": {
- "mtimeMs": 1778902489000,
+ "mtimeMs": 1778821213094.901,
"size": 10482,
"lines": 258,
"role": "Self-Reflector — 빈 깡통(Hollow Code) 검출 휴리스틱. Phase C(syntax/lint)는 문법 오류만 잡는다. 작은 LLM이 가장 자주 만드는 실패 패턴은 문법은 맞지만 본문이 비어 있는 코드 — def foo(): pass, # TODO: implement, import만 있고 로직 0줄인 모듈 등. 사용자가 \"완료 됐다\"라는",
"imports": []
},
"src/features/selfReflector/selfReflectorPrompt.ts": {
- "mtimeMs": 1778902489000,
+ "mtimeMs": 1778821145026.1665,
"size": 6139,
"lines": 108,
"role": "Self-Reflector — 답변 산출물의 자기 검증 레이어. Memory(기억) 단계는 이미 충분히 강하지만 Verification(검증) 단계는 사용자 피드백에 의존적이다. 이 모듈은 그 격차를 메꾸는 3단 구조: Phase A (이 파일) ─ 시스템 프롬프트에 self-check 체크리스트 룰을 박아 LLM이 응답 마지막에 [Self-Reflecto",
"imports": []
},
"src/features/selfReflector/selfReflectorVerifier.ts": {
- "mtimeMs": 1778902489000,
+ "mtimeMs": 1778821237110.5894,
"size": 7495,
"lines": 172,
"role": "Self-Reflector Phase B — 분리된 콘텍스트에서 LLM 한 번 더 호출해 응답을 외부 시각으로 검증. Phase A의 self-check는 같은 모델·같은 콘텍스트에서 자기 자신을 보는 한계가 있다. 모델이 자기가 만든 답변을 자신 있게 잘못 평가하는 과신 편향은 LLM의 잘 알려진 약점이다. Phase B는 이걸 보완하기 위해: 1. sp",
@@ -871,9 +889,9 @@
]
},
"src/features/settings/settingsPanelProvider.ts": {
- "mtimeMs": 1778943856000,
- "size": 29429,
- "lines": 646,
+ "mtimeMs": 1779250671140.83,
+ "size": 32311,
+ "lines": 686,
"role": "",
"imports": [
"src/integrations/telegram/telegramClient",
@@ -886,8 +904,8 @@
]
},
"src/features/sheets/index.ts": {
- "mtimeMs": 1778935930000,
- "size": 237,
+ "mtimeMs": 1779065453886.916,
+ "size": 250,
"lines": 13,
"role": "",
"imports": [
@@ -895,8 +913,8 @@
]
},
"src/features/sheets/sheetsApi.ts": {
- "mtimeMs": 1778936110000,
- "size": 7794,
+ "mtimeMs": 1779065453887.9194,
+ "size": 7960,
"lines": 166,
"role": "Google Sheets API v4 — read / write / append. 토큰은 calendar 와 공유 (같은 OAuth 에 spreadsheets scope 포함). 별도 셋업 없음 — \"Astra: Google Calendar OAuth 연결\" 명령으로 한 번 로그인하면 둘 다 동작한다. 외부 라이브러리 안 씀 — Sheets API REST",
"imports": [
@@ -904,8 +922,8 @@
]
},
"src/features/tasks/index.ts": {
- "mtimeMs": 1778936468000,
- "size": 225,
+ "mtimeMs": 1779065453887.9194,
+ "size": 238,
"lines": 13,
"role": "",
"imports": [
@@ -913,15 +931,15 @@
]
},
"src/features/tasks/taskStore.ts": {
- "mtimeMs": 1778936462000,
- "size": 9121,
+ "mtimeMs": 1779065453888.9917,
+ "size": 9366,
"lines": 245,
"role": "Task tracker — .astra/company/shared/tasks.md 단일 파일. 설계 원칙: - 외부 DB 없이 사람이 읽을 수 있는 마크다운 테이블에 누적. git 으로 history 추적 가능. - 파싱은 regex 기반 (셀 구분자 |). 사용자가 손으로 편집해도 fault-tolerant. - 모든 task 는 안정적 id (t001,",
"imports": []
},
"src/integrations/telegram/conversationHistory.ts": {
- "mtimeMs": 1778684811000,
- "size": 6273,
+ "mtimeMs": 1778720117535.294,
+ "size": 6427,
"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": [
@@ -929,8 +947,8 @@
]
},
"src/integrations/telegram/telegramBot.ts": {
- "mtimeMs": 1778421270000,
- "size": 11344,
+ "mtimeMs": 1778549008903.0078,
+ "size": 11614,
"lines": 270,
"role": "",
"imports": [
@@ -940,8 +958,8 @@
]
},
"src/integrations/telegram/telegramClient.ts": {
- "mtimeMs": 1778252333000,
- "size": 5873,
+ "mtimeMs": 1778549008904.013,
+ "size": 6027,
"lines": 154,
"role": "",
"imports": [
@@ -950,22 +968,22 @@
]
},
"src/integrations/telegram/types.ts": {
- "mtimeMs": 1778252305000,
- "size": 1255,
+ "mtimeMs": 1778549008904.013,
+ "size": 1309,
"lines": 54,
"role": "Subset of the Telegram Bot API types we actually consume. Source: https://core.telegram.org/bots/api Only fields the bot reads or writes are typed — leaving the rest as unknown keeps the surface narro",
"imports": []
},
"src/lib/contextManager.ts": {
- "mtimeMs": 1778597095000,
- "size": 12982,
+ "mtimeMs": 1778664139961.0637,
+ "size": 13257,
"lines": 275,
"role": "Context Manager (컨텍스트 한계 관리) \"context length = 132k\" 는 \"답변을 132k 토큰까지 생성해도 된다\" 가 아닙니다. 시스템 프롬프트 + 대화 기록 + 입력 문서 + 생성될 답변 + 여유분 ≤ context length 이 모듈은 요청을 보내기 전에 입력 토큰을 추정하고, - 동적으로 출력 상한(maxTokens)을 계",
"imports": []
},
"src/lib/diagnostics.ts": {
- "mtimeMs": 1777978189000,
- "size": 8389,
+ "mtimeMs": 1778028987412.5159,
+ "size": 8599,
"lines": 210,
"role": "",
"imports": [
@@ -973,8 +991,8 @@
]
},
"src/lib/discoverModels.ts": {
- "mtimeMs": 1778255896000,
- "size": 1555,
+ "mtimeMs": 1778549008905.0132,
+ "size": 1590,
"lines": 35,
"role": "",
"imports": [
@@ -982,8 +1000,8 @@
]
},
"src/lib/engine.ts": {
- "mtimeMs": 1778763448000,
- "size": 42698,
+ "mtimeMs": 1778807413498.881,
+ "size": 43604,
"lines": 906,
"role": "",
"imports": [
@@ -998,8 +1016,8 @@
]
},
"src/lib/formatter.ts": {
- "mtimeMs": 1777980992000,
- "size": 3851,
+ "mtimeMs": 1778028987413.7585,
+ "size": 3932,
"lines": 81,
"role": "",
"imports": [
@@ -1007,22 +1025,22 @@
]
},
"src/lib/paths.ts": {
- "mtimeMs": 1778591351000,
- "size": 6416,
+ "mtimeMs": 1778664139961.0637,
+ "size": 6567,
"lines": 151,
"role": "",
"imports": []
},
"src/lmstudio/activityTracker.ts": {
- "mtimeMs": 1778246443000,
- "size": 426,
+ "mtimeMs": 1778549008906.526,
+ "size": 445,
"lines": 19,
"role": "",
"imports": []
},
"src/lmstudio/client.ts": {
- "mtimeMs": 1778472808000,
- "size": 5773,
+ "mtimeMs": 1778549008907.0293,
+ "size": 5920,
"lines": 147,
"role": "",
"imports": [
@@ -1030,8 +1048,8 @@
]
},
"src/lmstudio/lifecycleManager.ts": {
- "mtimeMs": 1778251087000,
- "size": 10783,
+ "mtimeMs": 1778549008907.0293,
+ "size": 11074,
"lines": 291,
"role": "",
"imports": [
@@ -1042,8 +1060,8 @@
]
},
"src/lmstudio/streamer.ts": {
- "mtimeMs": 1778598444000,
- "size": 7762,
+ "mtimeMs": 1778664139962.1995,
+ "size": 7924,
"lines": 162,
"role": "",
"imports": [
@@ -1052,65 +1070,17 @@
]
},
"src/memory/EpisodicMemory.ts": {
- "mtimeMs": 1777858161000,
- "size": 9577,
- "lines": 278,
+ "mtimeMs": 1779411639504.3022,
+ "size": 10940,
+ "lines": 297,
"role": "Episodic Memory (일화 기억) 과거 대화/회의/결정의 맥락 흐름을 저장합니다. 세션 종료 시 자동으로 에피소드를 요약하여 저장합니다. \"왜 이렇게 결정했는지\", \"어떤 흐름으로 진행했는지\" 기록. 저장 위치: {brainPath}/memory/episodes/.json",
"imports": [
"src/memory/types"
]
},
- "src/memory/LongTermMemory.ts": {
- "mtimeMs": 1777858068000,
- "size": 8364,
- "lines": 243,
- "role": "Long-Term Memory (장기 기억) 사용자의 취향, 프로젝트 목표, 반복 규칙, 과거 결정 사항을 영구적으로 저장하고 관리합니다. 저장 위치: {brainPath}/memory/longterm.json",
- "imports": [
- "src/memory/types"
- ]
- },
- "src/memory/MemoryExtractor.ts": {
- "mtimeMs": 1777858183000,
- "size": 3838,
- "lines": 115,
- "role": "Memory Extractor (기억 추출기) 대화 종료 시 히스토리를 분석하여 각 메모리 레이어에 저장할 정보를 자동으로 추출합니다. LLM 호출 없이 패턴 매칭 기반으로 동작합니다.",
- "imports": [
- "src/memory/LongTermMemory",
- "src/memory/ProjectMemory",
- "src/memory/EpisodicMemory"
- ]
- },
- "src/memory/ProceduralMemory.ts": {
- "mtimeMs": 1777858120000,
- "size": 5533,
- "lines": 173,
- "role": "Procedural Memory (절차 기억) 반복 작업의 절차와 패턴을 관리합니다. 기존 skill.md 시스템과 통합되어, Brain의 memory/procedures/ 아래의 MD 파일을 스캔하여 절차를 로드합니다. 저장 위치: {brainPath}/memory/procedures/.md",
- "imports": [
- "src/memory/types"
- ]
- },
- "src/memory/ProjectMemory.ts": {
- "mtimeMs": 1777864677000,
- "size": 6533,
- "lines": 212,
- "role": "Project Memory (프로젝트 기억) 프로젝트별 요구사항, 코드 구조, 아키텍처 결정, 버그 기록 등을 Astra 확장 프로그램 내부에 저장하고 관리합니다. 저장 위치: {ConnectAI}/.astra/projectmemory.json (기존: {projectRoot}/.astra/ → 변경됨)",
- "imports": [
- "src/memory/types",
- "src/core/astraPath"
- ]
- },
- "src/memory/ShortTermMemory.ts": {
- "mtimeMs": 1777858031000,
- "size": 1167,
- "lines": 37,
- "role": "Short-Term Memory (단기 기억) 현재 대화의 즉시 맥락을 관리합니다. FIFO 방식으로 최근 N개 메시지를 유지합니다.",
- "imports": [
- "src/memory/types"
- ]
- },
"src/memory/index.ts": {
- "mtimeMs": 1777858214000,
- "size": 6310,
+ "mtimeMs": 1779411771475.9016,
+ "size": 6530,
"lines": 188,
"role": "MemoryManager — 5-Layer Cognitive Memory System (통합 진입점) Astra의 모든 메모리 레이어를 통합 관리하는 중앙 매니저입니다. ① Short-Term Memory — 현재 대화 흐름 (FIFO) ② Long-Term Memory — 사용자 취향/규칙/결정 ③ Project Memory — 프로젝트별 지식 ④ Pro",
"imports": [
@@ -1124,16 +1094,64 @@
"src/memory/types"
]
},
+ "src/memory/LongTermMemory.ts": {
+ "mtimeMs": 1779411767886.338,
+ "size": 9226,
+ "lines": 252,
+ "role": "Long-Term Memory (장기 기억) 사용자의 취향, 프로젝트 목표, 반복 규칙, 과거 결정 사항을 영구적으로 저장하고 관리합니다. 저장 위치: {brainPath}/memory/longterm.json",
+ "imports": [
+ "src/memory/types"
+ ]
+ },
+ "src/memory/MemoryExtractor.ts": {
+ "mtimeMs": 1778028987415.8738,
+ "size": 3953,
+ "lines": 115,
+ "role": "Memory Extractor (기억 추출기) 대화 종료 시 히스토리를 분석하여 각 메모리 레이어에 저장할 정보를 자동으로 추출합니다. LLM 호출 없이 패턴 매칭 기반으로 동작합니다.",
+ "imports": [
+ "src/memory/LongTermMemory",
+ "src/memory/ProjectMemory",
+ "src/memory/EpisodicMemory"
+ ]
+ },
+ "src/memory/ProceduralMemory.ts": {
+ "mtimeMs": 1778028987416.5232,
+ "size": 5706,
+ "lines": 173,
+ "role": "Procedural Memory (절차 기억) 반복 작업의 절차와 패턴을 관리합니다. 기존 skill.md 시스템과 통합되어, Brain의 memory/procedures/ 아래의 MD 파일을 스캔하여 절차를 로드합니다. 저장 위치: {brainPath}/memory/procedures/.md",
+ "imports": [
+ "src/memory/types"
+ ]
+ },
+ "src/memory/ProjectMemory.ts": {
+ "mtimeMs": 1778028987417.0342,
+ "size": 6745,
+ "lines": 212,
+ "role": "Project Memory (프로젝트 기억) 프로젝트별 요구사항, 코드 구조, 아키텍처 결정, 버그 기록 등을 Astra 확장 프로그램 내부에 저장하고 관리합니다. 저장 위치: {ConnectAI}/.astra/projectmemory.json (기존: {projectRoot}/.astra/ → 변경됨)",
+ "imports": [
+ "src/memory/types",
+ "src/core/astraPath"
+ ]
+ },
+ "src/memory/ShortTermMemory.ts": {
+ "mtimeMs": 1778028987418.1267,
+ "size": 1204,
+ "lines": 37,
+ "role": "Short-Term Memory (단기 기억) 현재 대화의 즉시 맥락을 관리합니다. FIFO 방식으로 최근 N개 메시지를 유지합니다.",
+ "imports": [
+ "src/memory/types"
+ ]
+ },
"src/memory/types.ts": {
- "mtimeMs": 1777858019000,
- "size": 3449,
+ "mtimeMs": 1778028987419.3413,
+ "size": 3575,
"lines": 126,
"role": "Memory Type Definitions (메모리 타입 정의) Astra의 5-Layer Cognitive Memory System의 모든 타입을 정의합니다. ① Short-Term ② Long-Term ③ Project ④ Procedural ⑤ Episodic",
"imports": []
},
"src/retrieval/brainIndex.ts": {
- "mtimeMs": 1778674336000,
- "size": 12945,
+ "mtimeMs": 1778667252738.4248,
+ "size": 13270,
"lines": 325,
"role": "Brain Index — persistent, mtime-keyed tokenized cache of the Second Brain RAG 검색은 매 질의마다 브레인의 모든 .md 파일을 읽고 토크나이즈해서 TF-IDF 점수를 계산했습니다 — 파일 수가 많아지면 그게 병목입니다. 이 모듈은 /.astra/brain-index.json 에",
"imports": [
@@ -1143,8 +1161,8 @@
]
},
"src/retrieval/contextBudget.ts": {
- "mtimeMs": 1778674336000,
- "size": 5143,
+ "mtimeMs": 1778665501089.1736,
+ "size": 5283,
"lines": 140,
"role": "Context Budget Manager (컨텍스트 예산 관리) 시스템 프롬프트의 토큰 예산을 관리하여 로컬 모델의 context window를 효율적으로 활용합니다.",
"imports": [
@@ -1152,7 +1170,7 @@
]
},
"src/retrieval/embeddings.ts": {
- "mtimeMs": 1778674336000,
+ "mtimeMs": 1778667198243.6443,
"size": 7294,
"lines": 167,
"role": "Embeddings — local hybrid (sparse + dense) retrieval support TF-IDF is fast and zero-cost but misses synonyms / paraphrase. A small local embedding model (BGE-small, multilingual-e5-small, nomic-embed",
@@ -1161,8 +1179,8 @@
]
},
"src/retrieval/index.ts": {
- "mtimeMs": 1778676255000,
- "size": 23764,
+ "mtimeMs": 1778720117542.9775,
+ "size": 24278,
"lines": 514,
"role": "RetrievalOrchestrator — Unified RAG Pipeline Astra의 모든 검색 소스를 통합 관리하는 오케스트레이터입니다. 검색 흐름: ① Query Planning — 의도 분류 + 검색 전략 결정 ② Parallel Search — Brain + Memory + Project + Episode 동시 검색 ③ Result Fusio",
"imports": [
@@ -1179,8 +1197,8 @@
]
},
"src/retrieval/knowledgeMix.ts": {
- "mtimeMs": 1778902489000,
- "size": 7621,
+ "mtimeMs": 1778821115241.6562,
+ "size": 7786,
"lines": 165,
"role": "Knowledge Mix — model 지식 vs Second Brain 지식의 상대 비율을 LLM에게 전달하는 정책 레이어. ── 정책 v2 (상대값+상대값=상대값) ────────────────────────────────────── weight는 0~100 정수이지만 상대 비율로만 해석한다. 즉 \"70\"은 \"100% 중 70%\"라는 상대 표현이고, 시",
"imports": [
@@ -1189,8 +1207,8 @@
]
},
"src/retrieval/lessonHelpers.ts": {
- "mtimeMs": 1778674336000,
- "size": 14134,
+ "mtimeMs": 1778665428445.0337,
+ "size": 14459,
"lines": 325,
"role": "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",
"imports": [
@@ -1198,22 +1216,22 @@
]
},
"src/retrieval/scoring.ts": {
- "mtimeMs": 1778674336000,
- "size": 20793,
- "lines": 518,
+ "mtimeMs": 1779411675045.9507,
+ "size": 22287,
+ "lines": 536,
"role": "Scoring Engine — TF-IDF + Bilingual Tokenizer 단순 includes() 키워드 매칭을 넘어서, TF-IDF 가중치 기반의 문서 스코어링을 제공합니다. 한국어/영어 양국어 토크나이저를 포함합니다.",
"imports": []
},
"src/retrieval/types.ts": {
- "mtimeMs": 1778674336000,
- "size": 2424,
+ "mtimeMs": 1778665510728.6262,
+ "size": 2490,
"lines": 66,
"role": "Retrieval Types (검색 결과 통합 타입) 모든 검색 소스(Brain, Memory, Project, Episode)의 결과를 통합 인터페이스로 정의합니다.",
"imports": []
},
"src/scaffolder/projectScaffolder.ts": {
- "mtimeMs": 1778251854000,
- "size": 4508,
+ "mtimeMs": 1778549008910.5835,
+ "size": 4619,
"lines": 111,
"role": "",
"imports": [
@@ -1223,22 +1241,22 @@
]
},
"src/scaffolder/templates.ts": {
- "mtimeMs": 1778251830000,
- "size": 4897,
+ "mtimeMs": 1778549008910.5835,
+ "size": 5051,
"lines": 154,
"role": "Scaffolder template catalog. Templates are pure data — (projectName) => { [relativePath]: contents }. New templates are added by appending to TEMPLATES; the rest of the scaffolder (validation, IO, com",
"imports": []
},
"src/security.ts": {
- "mtimeMs": 1778169995000,
- "size": 3310,
- "lines": 90,
+ "mtimeMs": 1779429436188.0647,
+ "size": 6053,
+ "lines": 154,
"role": "",
"imports": []
},
"src/sidebar/agentHandlers.ts": {
- "mtimeMs": 1778676515000,
- "size": 7752,
+ "mtimeMs": 1778720117552.737,
+ "size": 7921,
"lines": 169,
"role": "",
"imports": [
@@ -1248,8 +1266,8 @@
]
},
"src/sidebar/brainHandlers.ts": {
- "mtimeMs": 1778248976000,
- "size": 1080,
+ "mtimeMs": 1778549008912.5908,
+ "size": 1113,
"lines": 33,
"role": "",
"imports": [
@@ -1257,14 +1275,15 @@
]
},
"src/sidebar/chatHandlers.ts": {
- "mtimeMs": 1778934077000,
- "size": 37222,
- "lines": 676,
+ "mtimeMs": 1779343234943.2488,
+ "size": 40131,
+ "lines": 707,
"role": "",
"imports": [
"src/sidebarProvider",
"src/utils",
"src/lib/paths",
+ "src/features/datacollect/slashRouter",
"src/config",
"src/features/company",
"src/core/services",
@@ -1272,8 +1291,8 @@
]
},
"src/sidebar/chronicleHandlers.ts": {
- "mtimeMs": 1778248986000,
- "size": 2068,
+ "mtimeMs": 1778549008912.5908,
+ "size": 2120,
"lines": 52,
"role": "",
"imports": [
@@ -1281,9 +1300,9 @@
]
},
"src/sidebarProvider.ts": {
- "mtimeMs": 1778941620000,
- "size": 189927,
- "lines": 4165,
+ "mtimeMs": 1779411747417.136,
+ "size": 198818,
+ "lines": 4226,
"role": "",
"imports": [
"src/utils",
@@ -1298,6 +1317,7 @@
"src/sidebar/chronicleHandlers",
"src/sidebar/agentHandlers",
"src/skills/agentKnowledgeMap",
+ "src/retrieval/brainIndex",
"src/lib/contextManager",
"src/skills/externalSkillLoader",
"src/features/projectArchitecture",
@@ -1309,8 +1329,8 @@
]
},
"src/skills/agentKnowledgeMap.ts": {
- "mtimeMs": 1778676092000,
- "size": 15707,
+ "mtimeMs": 1778720117565.968,
+ "size": 16081,
"lines": 374,
"role": "",
"imports": [
@@ -1319,8 +1339,8 @@
]
},
"src/skills/externalSkillLoader.ts": {
- "mtimeMs": 1778470672000,
- "size": 5859,
+ "mtimeMs": 1778549008916.6155,
+ "size": 6018,
"lines": 159,
"role": "",
"imports": [
@@ -1329,20 +1349,21 @@
]
},
"src/skills/scopedBrainRetriever.ts": {
- "mtimeMs": 1778419289000,
- "size": 5706,
- "lines": 153,
+ "mtimeMs": 1779411581885.858,
+ "size": 6369,
+ "lines": 156,
"role": "",
"imports": [
"src/utils",
"src/lib/paths",
"src/retrieval/scoring",
+ "src/retrieval/brainIndex",
"src/retrieval/contextBudget"
]
},
"src/skills/skillInjectionService.ts": {
- "mtimeMs": 1778681774000,
- "size": 6276,
+ "mtimeMs": 1778549008918.12,
+ "size": 6421,
"lines": 145,
"role": "",
"imports": [
@@ -1351,23 +1372,23 @@
]
},
"src/system/specs.ts": {
- "mtimeMs": 1778251036000,
- "size": 4326,
+ "mtimeMs": 1778549008918.12,
+ "size": 4444,
"lines": 118,
"role": "",
"imports": []
},
"src/types/interfaces.ts": {
- "mtimeMs": 1778169995000,
- "size": 1260,
+ "mtimeMs": 1778036927218.7627,
+ "size": 1299,
"lines": 39,
"role": "Service Interfaces (서비스 인터페이스 정의) 각 서비스(Agent, Brain, FileSystem 등)의 추상화 인터페이스를 정의합니다. 의존성 주입(DI)과 단위 테스트를 위해 필수적입니다.",
"imports": []
},
"src/utils.ts": {
- "mtimeMs": 1778936575000,
- "size": 15995,
- "lines": 360,
+ "mtimeMs": 1779428605818.0505,
+ "size": 20391,
+ "lines": 408,
"role": "",
"imports": [
"src/config",
@@ -1375,50 +1396,50 @@
]
},
"media/settings-panel.css": {
- "mtimeMs": 1778255405000,
- "size": 4546,
+ "mtimeMs": 1778549008877.4587,
+ "size": 4756,
"lines": 210,
"role": "Stylesheet",
"imports": []
},
"media/settings-panel.html": {
- "mtimeMs": 1778943830000,
- "size": 17362,
- "lines": 328,
+ "mtimeMs": 1779250684699.01,
+ "size": 20873,
+ "lines": 373,
"role": "Astra Settings",
"imports": []
},
"media/settings-panel.js": {
- "mtimeMs": 1778943881000,
- "size": 19114,
- "lines": 411,
+ "mtimeMs": 1779250701675.4397,
+ "size": 21239,
+ "lines": 445,
"role": "",
"imports": []
},
"media/sidebar.css": {
- "mtimeMs": 1778943817000,
- "size": 88173,
- "lines": 2068,
+ "mtimeMs": 1779065453854.1843,
+ "size": 90311,
+ "lines": 2078,
"role": "Stylesheet",
"imports": []
},
"media/sidebar.html": {
- "mtimeMs": 1778934094000,
- "size": 34587,
- "lines": 546,
+ "mtimeMs": 1779083405649.7578,
+ "size": 34977,
+ "lines": 545,
"role": "Astra",
"imports": []
},
"media/sidebar.js": {
- "mtimeMs": 1778943769000,
- "size": 214022,
- "lines": 3680,
+ "mtimeMs": 1779083454849.123,
+ "size": 217481,
+ "lines": 3677,
"role": "",
"imports": []
},
"tests/agentEngine.test.ts": {
- "mtimeMs": 1778690770000,
- "size": 33921,
+ "mtimeMs": 1778720117574.2246,
+ "size": 34703,
"lines": 782,
"role": "AgentEngine Integration Tests & Performance Benchmarks 검증 대상: 1. ErrorClassifier — 오류 유형(Transient/Permanent/Abort) 자동 분류 2. ErrorRecoveryMatrix — 각 규칙이 의도한 대응 전략으로 매핑되는지 검증 3. resilientExecute — 지수 백",
"imports": [
@@ -1426,8 +1447,8 @@
]
},
"tests/approvalQueue.test.ts": {
- "mtimeMs": 1778251690000,
- "size": 5915,
+ "mtimeMs": 1778549008920.1624,
+ "size": 6079,
"lines": 164,
"role": "Unit tests for ApprovalQueue. Strategy: drive enqueue → approve / reject / clear / pre-empt directly, confirm the onChange event fires at the right moments and callbacks fire exactly once.",
"imports": [
@@ -1435,8 +1456,8 @@
]
},
"tests/brainIndex.test.ts": {
- "mtimeMs": 1778594450000,
- "size": 5406,
+ "mtimeMs": 1778664139970.806,
+ "size": 5513,
"lines": 107,
"role": "",
"imports": [
@@ -1444,8 +1465,8 @@
]
},
"tests/calendarApi.test.ts": {
- "mtimeMs": 1778935637000,
- "size": 5103,
+ "mtimeMs": 1779065453894.5227,
+ "size": 5234,
"lines": 131,
"role": "",
"imports": [
@@ -1454,8 +1475,8 @@
]
},
"tests/contextManager.test.ts": {
- "mtimeMs": 1778594523000,
- "size": 6545,
+ "mtimeMs": 1778664139971.9563,
+ "size": 6674,
"lines": 129,
"role": "",
"imports": [
@@ -1463,8 +1484,8 @@
]
},
"tests/dataProcessor.test.ts": {
- "mtimeMs": 1777808065000,
- "size": 3430,
+ "mtimeMs": 1778028987448.8394,
+ "size": 3517,
"lines": 87,
"role": "/ ",
"imports": [
@@ -1472,8 +1493,8 @@
]
},
"tests/devilAgent.test.ts": {
- "mtimeMs": 1778943907000,
- "size": 3179,
+ "mtimeMs": 1779065453895.5222,
+ "size": 3240,
"lines": 61,
"role": "",
"imports": [
@@ -1481,8 +1502,8 @@
]
},
"tests/findBrainFilesCache.test.ts": {
- "mtimeMs": 1778247665000,
- "size": 2720,
+ "mtimeMs": 1778549008921.7842,
+ "size": 2800,
"lines": 80,
"role": "Unit tests for findBrainFiles TTL cache.",
"imports": [
@@ -1490,8 +1511,8 @@
]
},
"tests/icsParser.test.ts": {
- "mtimeMs": 1778934828000,
- "size": 5011,
+ "mtimeMs": 1779065453895.5222,
+ "size": 5145,
"lines": 134,
"role": "",
"imports": [
@@ -1499,8 +1520,8 @@
]
},
"tests/integration_retrieval.test.ts": {
- "mtimeMs": 1777949141000,
- "size": 4017,
+ "mtimeMs": 1778028987449.4358,
+ "size": 4108,
"lines": 91,
"role": "",
"imports": [
@@ -1509,8 +1530,8 @@
]
},
"tests/lessonHelpers.test.ts": {
- "mtimeMs": 1778595482000,
- "size": 9400,
+ "mtimeMs": 1778664139972.9592,
+ "size": 9591,
"lines": 191,
"role": "",
"imports": [
@@ -1518,8 +1539,8 @@
]
},
"tests/lmStudioLifecycle.test.ts": {
- "mtimeMs": 1778250254000,
- "size": 11385,
+ "mtimeMs": 1778549008921.7842,
+ "size": 11703,
"lines": 318,
"role": "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",
"imports": [
@@ -1529,8 +1550,8 @@
]
},
"tests/lmStudioStreamer.test.ts": {
- "mtimeMs": 1778591604000,
- "size": 8660,
+ "mtimeMs": 1778664139973.4685,
+ "size": 8880,
"lines": 220,
"role": "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.",
"imports": [
@@ -1539,8 +1560,8 @@
]
},
"tests/localPathPreflight.test.ts": {
- "mtimeMs": 1778595955000,
- "size": 23687,
+ "mtimeMs": 1778664139974.819,
+ "size": 24177,
"lines": 490,
"role": "",
"imports": [
@@ -1548,15 +1569,15 @@
]
},
"tests/mocks/vscode.js": {
- "mtimeMs": 1778246810000,
- "size": 1670,
+ "mtimeMs": 1778549008931.3582,
+ "size": 1738,
"lines": 68,
"role": "",
"imports": []
},
"tests/officeSchema.test.ts": {
- "mtimeMs": 1778932509000,
- "size": 9884,
+ "mtimeMs": 1779065453896.7021,
+ "size": 10125,
"lines": 241,
"role": "",
"imports": [
@@ -1566,8 +1587,8 @@
]
},
"tests/paths.test.ts": {
- "mtimeMs": 1778250990000,
- "size": 2590,
+ "mtimeMs": 1778549008931.3582,
+ "size": 2674,
"lines": 84,
"role": "Unit tests for the centralized path resolver.",
"imports": [
@@ -1575,8 +1596,8 @@
]
},
"tests/pipelineTemplates.test.ts": {
- "mtimeMs": 1778934174000,
- "size": 2984,
+ "mtimeMs": 1779065453897.361,
+ "size": 3053,
"lines": 69,
"role": "",
"imports": [
@@ -1584,8 +1605,8 @@
]
},
"tests/projectChronicle.test.ts": {
- "mtimeMs": 1778169995000,
- "size": 8359,
+ "mtimeMs": 1778029332769.3286,
+ "size": 8558,
"lines": 199,
"role": "",
"imports": [
@@ -1593,8 +1614,8 @@
]
},
"tests/projectChronicleGuardPrompt.test.ts": {
- "mtimeMs": 1777808369000,
- "size": 2838,
+ "mtimeMs": 1778028987452.0652,
+ "size": 2890,
"lines": 52,
"role": "",
"imports": [
@@ -1602,8 +1623,8 @@
]
},
"tests/projectScaffolder.test.ts": {
- "mtimeMs": 1778251915000,
- "size": 5800,
+ "mtimeMs": 1778549008932.6519,
+ "size": 5935,
"lines": 135,
"role": "Unit tests for FileSystemProjectScaffolder. Drives against a real temp directory so end-to-end file IO + path-traversal defenses are exercised.",
"imports": [
@@ -1611,8 +1632,8 @@
]
},
"tests/providers.test.ts": {
- "mtimeMs": 1778942187000,
- "size": 4118,
+ "mtimeMs": 1779065453898.3752,
+ "size": 4215,
"lines": 97,
"role": "",
"imports": [
@@ -1621,8 +1642,8 @@
]
},
"tests/resilience_stress.test.ts": {
- "mtimeMs": 1777968922000,
- "size": 6981,
+ "mtimeMs": 1778028987453.0332,
+ "size": 7164,
"lines": 183,
"role": "Resilience & Boundary Stress Test Suite (v2.77.3) 이 테스트는 ConnectAI 엔진이 극한의 환경(인증 실패, 네트워크 차단, 타임아웃 등)에서 얼마나 안정적으로 복구되고, 신뢰성 지표(Resilience Metrics)를 정확히 기록하는지 검증합니다.",
"imports": [
@@ -1630,8 +1651,8 @@
]
},
"tests/resilience_v4.test.ts": {
- "mtimeMs": 1777978211000,
- "size": 3435,
+ "mtimeMs": 1778028987453.5366,
+ "size": 3519,
"lines": 84,
"role": "",
"imports": [
@@ -1640,8 +1661,8 @@
]
},
"tests/responseRecovery.test.ts": {
- "mtimeMs": 1778598707000,
- "size": 8782,
+ "mtimeMs": 1778664139974.819,
+ "size": 8933,
"lines": 151,
"role": "",
"imports": [
@@ -1649,8 +1670,8 @@
]
},
"tests/scoring.test.ts": {
- "mtimeMs": 1778169995000,
- "size": 6055,
+ "mtimeMs": 1778043314856.5872,
+ "size": 6189,
"lines": 134,
"role": "",
"imports": [
@@ -1658,8 +1679,8 @@
]
},
"tests/secondBrainTrace.test.ts": {
- "mtimeMs": 1777866065000,
- "size": 23024,
+ "mtimeMs": 1778028987455.0378,
+ "size": 23431,
"lines": 407,
"role": "",
"imports": [
@@ -1667,8 +1688,8 @@
]
},
"tests/sheetsApi.test.ts": {
- "mtimeMs": 1778936029000,
- "size": 3913,
+ "mtimeMs": 1779065453899.3755,
+ "size": 4026,
"lines": 113,
"role": "",
"imports": [
@@ -1677,8 +1698,8 @@
]
},
"tests/skillInjectionService.test.ts": {
- "mtimeMs": 1778681774000,
- "size": 6741,
+ "mtimeMs": 1778549008933.6833,
+ "size": 6913,
"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",
"imports": [
@@ -1686,8 +1707,8 @@
]
},
"tests/systemPrompt.test.ts": {
- "mtimeMs": 1777966465000,
- "size": 1215,
+ "mtimeMs": 1778028987455.4153,
+ "size": 1244,
"lines": 29,
"role": "",
"imports": [
@@ -1695,8 +1716,8 @@
]
},
"tests/systemSpecs.test.ts": {
- "mtimeMs": 1778251130000,
- "size": 3464,
+ "mtimeMs": 1778549008934.187,
+ "size": 3554,
"lines": 90,
"role": "Unit tests for SystemSpecs + HeuristicModelMemoryEstimator. Strategy: - HeuristicModelMemoryEstimator is pure — directly drive it with model ids. - NodeSystemSpecsProvider depends on os. so we test: a",
"imports": [
@@ -1704,8 +1725,8 @@
]
},
"tests/taskStore.test.ts": {
- "mtimeMs": 1778936645000,
- "size": 7226,
+ "mtimeMs": 1779065453901.3855,
+ "size": 7411,
"lines": 185,
"role": "",
"imports": [
@@ -1714,8 +1735,8 @@
]
},
"tests/telegramBot.test.ts": {
- "mtimeMs": 1778253785000,
- "size": 13012,
+ "mtimeMs": 1778549008934.187,
+ "size": 13375,
"lines": 363,
"role": "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",
"imports": [
@@ -1725,8 +1746,8 @@
]
},
"tests/transaction.test.ts": {
- "mtimeMs": 1777808065000,
- "size": 2064,
+ "mtimeMs": 1777511752614.9685,
+ "size": 2132,
"lines": 68,
"role": "/ ",
"imports": [
@@ -1734,8 +1755,8 @@
]
},
"tests/vulnerability.test.ts": {
- "mtimeMs": 1777808065000,
- "size": 2100,
+ "mtimeMs": 1777511752615.9702,
+ "size": 2160,
"lines": 60,
"role": "/ ",
"imports": [
@@ -1744,615 +1765,643 @@
]
},
"core_py/events.py": {
- "mtimeMs": 1777559069000,
- "size": 2374,
+ "mtimeMs": 1778028987265.2336,
+ "size": 2438,
"lines": 64,
"role": "",
"imports": []
},
"core_py/inference.py": {
- "mtimeMs": 1777559249000,
- "size": 3834,
+ "mtimeMs": 1778028987265.8833,
+ "size": 3925,
"lines": 91,
"role": "",
"imports": []
},
"core_py/loader.py": {
- "mtimeMs": 1777559060000,
- "size": 2368,
+ "mtimeMs": 1778028987266.8376,
+ "size": 2429,
"lines": 61,
"role": "",
"imports": []
},
"core_py/monitoring.py": {
- "mtimeMs": 1777559685000,
- "size": 2060,
+ "mtimeMs": 1778028987266.8376,
+ "size": 2116,
"lines": 56,
"role": "",
"imports": []
},
"core_py/optimizer.py": {
- "mtimeMs": 1777559265000,
- "size": 2327,
+ "mtimeMs": 1778028987267.4917,
+ "size": 2382,
"lines": 55,
"role": "",
"imports": []
},
"core_py/queue_worker.py": {
- "mtimeMs": 1777559676000,
- "size": 2987,
+ "mtimeMs": 1778028987268.5847,
+ "size": 3069,
"lines": 82,
"role": "",
"imports": []
},
+ "docs/Advanced_Features_Implementation_Guide.md": {
+ "mtimeMs": 1778028987294.7693,
+ "size": 1844,
+ "lines": 40,
+ "role": "Advanced Features Implementation Guide",
+ "imports": []
+ },
+ "docs/AgentEngine_Architecture.md": {
+ "mtimeMs": 1778028987295.9912,
+ "size": 14652,
+ "lines": 314,
+ "role": "AgentEngine Architecture Document",
+ "imports": []
+ },
"docs/ASTRA_OFFICE_REFACTOR.md": {
- "mtimeMs": 1778931177000,
- "size": 9395,
+ "mtimeMs": 1779065453844.1316,
+ "size": 9593,
"lines": 198,
"role": "Astra Office Refactor — Design Doc",
"imports": [
"docs/features/astraOffice"
]
},
- "docs/Advanced_Features_Implementation_Guide.md": {
- "mtimeMs": 1777808065000,
- "size": 1804,
- "lines": 40,
- "role": "Advanced Features Implementation Guide",
- "imports": []
- },
- "docs/AgentEngine_Architecture.md": {
- "mtimeMs": 1777863061000,
- "size": 14338,
- "lines": 314,
- "role": "AgentEngine Architecture Document",
- "imports": []
- },
- "docs/EXPERIENCE_MEMORY_PLAN.md": {
- "mtimeMs": 1778595595000,
- "size": 9390,
- "lines": 122,
- "role": "Experience Memory (Mistake / Lesson Loop) — Implementation Plan",
- "imports": []
- },
- "docs/PROJECT_CHRONICLE_GUARD_ROADMAP.md": {
- "mtimeMs": 1777948230000,
- "size": 1634,
- "lines": 43,
- "role": "Project Chronicle Guard: Search Engine Roadmap",
- "imports": []
- },
- "docs/TELEGRAM_REMOTE_EXECUTION_PLAN.md": {
- "mtimeMs": 1778592247000,
- "size": 12254,
- "lines": 452,
- "role": "Telegram Remote Execution 기획서",
- "imports": []
- },
- "docs/UX_UI_Consistency_Guidelines.md": {
- "mtimeMs": 1777808065000,
- "size": 2509,
- "lines": 44,
- "role": "UX/UI Consistency Guidelines",
- "imports": []
- },
- "docs/docs/records/docs/README.md": {
- "mtimeMs": 1777949758000,
- "size": 427,
- "lines": 18,
- "role": "docs Chronicle Records",
- "imports": []
- },
"docs/docs/records/docs/bugs/BUG-0001-viewed-integration-retrieval-test-ts-1-59-integration-retrie.md": {
- "mtimeMs": 1777949758000,
- "size": 2059,
+ "mtimeMs": 1778028987313.924,
+ "size": 2075,
"lines": 16,
"role": "Bug: Viewed integrationretrieval.test.ts:1-59 integrationretrieval.test.ts를 통해 ...",
"imports": []
},
"docs/docs/records/docs/chronicle.config.json": {
- "mtimeMs": 1777949758000,
- "size": 522,
+ "mtimeMs": 1778028987314.4072,
+ "size": 533,
"lines": 11,
"role": "JSON configuration",
"imports": []
},
"docs/docs/records/docs/project-profile.md": {
- "mtimeMs": 1777949758000,
- "size": 586,
+ "mtimeMs": 1778028987314.9126,
+ "size": 617,
"lines": 31,
"role": "Project Profile",
"imports": []
},
+ "docs/docs/records/docs/README.md": {
+ "mtimeMs": 1778028987312.8103,
+ "size": 445,
+ "lines": 18,
+ "role": "docs Chronicle Records",
+ "imports": []
+ },
"docs/docs/records/docs/timeline.md": {
- "mtimeMs": 1777949758000,
- "size": 210,
+ "mtimeMs": 1778028987315.4329,
+ "size": 217,
"lines": 7,
"role": "Project Timeline",
"imports": []
},
- "docs/records/ConnectAI/README.md": {
- "mtimeMs": 1777808202000,
- "size": 598,
- "lines": 18,
- "role": "Astra Project Chronicle Records",
+ "docs/EXPERIENCE_MEMORY_PLAN.md": {
+ "mtimeMs": 1778664139926.1729,
+ "size": 9512,
+ "lines": 122,
+ "role": "Experience Memory (Mistake / Lesson Loop) — Implementation Plan",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0001-volumes-data-project-antigravity-connectai-프로젝트-코드-리뷰-해줄-수-있.md": {
- "mtimeMs": 1777865266000,
- "size": 1408,
+ "docs/PROJECT_CHRONICLE_GUARD_ROADMAP.md": {
+ "mtimeMs": 1778028987296.7407,
+ "size": 1677,
+ "lines": 43,
+ "role": "Project Chronicle Guard: Search Engine Roadmap",
+ "imports": []
+ },
+ "docs/records/ConnectAI/bugs/BUG-0001-volumes-data-project-antigravity-connectai-프로젝트-코드-리뷰-해줄-수-있.md": {
+ "mtimeMs": 1778028987317.1565,
+ "size": 1424,
"lines": 16,
"role": "Bug: /Volumes/Data/project/Antigravity/ConnectAI 프로젝트 코드 리뷰 해줄 수 있어? 개선할 부분이 있는지, 그러고...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0002-지금-내가-분석-요청하고-너가-답을-줄때-아래-템플릿에-맞춰-답을-써주고-있는데-개선-포인트가-있는지-확인해.md": {
- "mtimeMs": 1777889979000,
- "size": 2559,
+ "docs/records/ConnectAI/bugs/BUG-0002-지금-내가-분석-요청하고-너가-답을-줄때-아래-템플릿에-맞춰-답을-써주고-있는데-개선-포인트가-있는지-확인해.md": {
+ "mtimeMs": 1778028987317.6665,
+ "size": 2575,
"lines": 16,
"role": "Bug: 지금 내가 분석 요청하고 너가 답을 줄때 아래 템플릿에 맞춰 답을 써주고 있는데, 개선 포인트가 있는지 확인해줘. ## 내가 보는 위험 가장 큰...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0003-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md": {
- "mtimeMs": 1777962835000,
- "size": 1891,
+ "docs/records/ConnectAI/bugs/BUG-0003-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md": {
+ "mtimeMs": 1778028987320.982,
+ "size": 1907,
"lines": 16,
"role": "Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0004-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md": {
- "mtimeMs": 1777964236000,
- "size": 1883,
+ "docs/records/ConnectAI/bugs/BUG-0004-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md": {
+ "mtimeMs": 1778028987321.984,
+ "size": 1899,
"lines": 16,
"role": "Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0005-다시한번-답줘-volumes-data-project-antigravity-connectai-내-질문에-대한-.md": {
- "mtimeMs": 1777965245000,
- "size": 1868,
+ "docs/records/ConnectAI/bugs/BUG-0005-다시한번-답줘-volumes-data-project-antigravity-connectai-내-질문에-대한-.md": {
+ "mtimeMs": 1778028987322.4868,
+ "size": 1884,
"lines": 16,
"role": "Bug: 다시한번 답줘. /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0006-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md": {
- "mtimeMs": 1777965308000,
- "size": 1623,
+ "docs/records/ConnectAI/bugs/BUG-0006-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md": {
+ "mtimeMs": 1778028987322.9897,
+ "size": 1639,
"lines": 16,
"role": "Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0007-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md": {
- "mtimeMs": 1777965612000,
- "size": 1823,
+ "docs/records/ConnectAI/bugs/BUG-0007-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md": {
+ "mtimeMs": 1778028987322.9897,
+ "size": 1839,
"lines": 16,
"role": "Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0008-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md": {
- "mtimeMs": 1777966704000,
- "size": 1737,
+ "docs/records/ConnectAI/bugs/BUG-0008-volumes-data-project-antigravity-connectai-내-질문에-대한-답변이-잘-정리.md": {
+ "mtimeMs": 1778028987323.9915,
+ "size": 1753,
"lines": 16,
"role": "Bug: /Volumes/Data/project/Antigravity/ConnectAI 내 질문에 대한 답변이 잘 정리되서 알려주긴 하는데 focused...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0009-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md": {
- "mtimeMs": 1777977740000,
- "size": 2295,
+ "docs/records/ConnectAI/bugs/BUG-0009-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md": {
+ "mtimeMs": 1778028987324.4944,
+ "size": 2311,
"lines": 16,
"role": "Bug: 문제점을 읽고 어떻게 개선하는게 최선인지 분석해주면 좋겠어. 알겠습니다. 지금부터 ConnectAI 프로젝트에만 완전히 집중하겠습니다. ...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0010-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md": {
- "mtimeMs": 1777981089000,
- "size": 2339,
+ "docs/records/ConnectAI/bugs/BUG-0010-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md": {
+ "mtimeMs": 1778028987324.9973,
+ "size": 2355,
"lines": 16,
"role": "Bug: 문제점을 읽고 어떻게 개선하는게 최선인지 분석해주면 좋겠어. 알겠습니다. 지금부터 ConnectAI 프로젝트에만 완전히 집중하겠습니다. ...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0011-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md": {
- "mtimeMs": 1777982331000,
- "size": 2277,
+ "docs/records/ConnectAI/bugs/BUG-0011-문제점을-읽고-어떻게-개선하는게-최선인지-분석해주면-좋겠어-알겠습니다-지금부터-connectai-프로젝트-에.md": {
+ "mtimeMs": 1778028987325.5178,
+ "size": 2293,
"lines": 16,
"role": "Bug: 문제점을 읽고 어떻게 개선하는게 최선인지 분석해주면 좋겠어. 알겠습니다. 지금부터 ConnectAI 프로젝트에만 완전히 집중하겠습니다. ...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0012-질문이-있어-논문을-쓰려고해-논문-주제는-서비스적이-아닌-사용자가-ai에게-구조로-질문을-해야-사용자의-의도.md": {
- "mtimeMs": 1778762677000,
+ "docs/records/ConnectAI/bugs/BUG-0012-질문이-있어-논문을-쓰려고해-논문-주제는-서비스적이-아닌-사용자가-ai에게-구조로-질문을-해야-사용자의-의도.md": {
+ "mtimeMs": 1778727537111.4634,
"size": 2354,
"lines": 16,
"role": "Bug: 질문이 있어. 논문을 쓰려고해. 논문 주제는 서비스적이 아닌 사용자가 ai에게 구조로 질문을 해야 사용자의 의도에 맞는 답변을 받을 수 있을까야...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0013-thesis-paper를-쓰려고-하는데-아래와-같이-쓰면-좋을까-이런-식으로-쓰면-되지-않을까-싶음-1-in.md": {
- "mtimeMs": 1778762677000,
+ "docs/records/ConnectAI/bugs/BUG-0013-thesis-paper를-쓰려고-하는데-아래와-같이-쓰면-좋을까-이런-식으로-쓰면-되지-않을까-싶음-1-in.md": {
+ "mtimeMs": 1778728112255.496,
"size": 2527,
"lines": 16,
"role": "Bug: Thesis paper를 쓰려고 하는데 아래와 같이 쓰면 좋을까? 이런 식으로 쓰면 되지 않을까 싶음 1. Introduction Thesis ...",
"imports": []
},
- "docs/records/ConnectAI/bugs/BUG-0014-논문-outline-title-인간-ai-상호작용에서-의도-정렬을-높이기-위한-최소-질의-구조-연구-또는-사.md": {
- "mtimeMs": 1778762677000,
+ "docs/records/ConnectAI/bugs/BUG-0014-논문-outline-title-인간-ai-상호작용에서-의도-정렬을-높이기-위한-최소-질의-구조-연구-또는-사.md": {
+ "mtimeMs": 1778728474713.4639,
"size": 2531,
"lines": 16,
"role": "Bug: 논문 Outline Title 인간-AI 상호작용에서 의도 정렬을 높이기 위한 최소 질의 구조 연구 또는 사용자의 인지적 편향을 보완하는 구조화...",
"imports": []
},
"docs/records/ConnectAI/chronicle.config.json": {
- "mtimeMs": 1779029444000,
- "size": 416,
+ "mtimeMs": 1779429578331.412,
+ "size": 371,
"lines": 11,
"role": "JSON configuration",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0001-volumes-data-project-antigravity-connectai-이-프로젝트를-지금-개발-중에-.md": {
- "mtimeMs": 1777860282000,
- "size": 1444,
+ "docs/records/ConnectAI/decisions/ADR-0001-volumes-data-project-antigravity-connectai-이-프로젝트를-지금-개발-중에-.md": {
+ "mtimeMs": 1778028987326.5986,
+ "size": 1463,
"lines": 19,
"role": "ADR: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트를 지금 개발 중에 있어. 코드 리뷰를 하고 잘된점과 ...",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0002-지금-너의-제2뇌-지식을-이용해서-아래-프로젝트-평가하고-앞으로-어느부분을-더-집중해서-개선을-하면-좋을지-.md": {
- "mtimeMs": 1777869330000,
- "size": 1878,
+ "docs/records/ConnectAI/decisions/ADR-0002-지금-너의-제2뇌-지식을-이용해서-아래-프로젝트-평가하고-앞으로-어느부분을-더-집중해서-개선을-하면-좋을지-.md": {
+ "mtimeMs": 1778028987326.5986,
+ "size": 1897,
"lines": 19,
"role": "ADR: 지금 너의 제2뇌 지식을 이용해서 아래 프로젝트 평가하고 앞으로 어느부분을 더 집중해서 개선을 하면 좋을지 알려주면 좋겠어. /Volumes/D...",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0003-volumes-data-project-antigravity-connectai-이-프로젝트-자체를-나는-자비스.md": {
- "mtimeMs": 1777877376000,
- "size": 1786,
+ "docs/records/ConnectAI/decisions/ADR-0003-volumes-data-project-antigravity-connectai-이-프로젝트-자체를-나는-자비스.md": {
+ "mtimeMs": 1778028987328.1038,
+ "size": 1805,
"lines": 19,
"role": "ADR: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 자체를 나는 자비스와 같은 툴로 만드는 것이 내 목표...",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0004-volumes-data-project-antigravity-connectai-이-프로젝트-자체를-나는-자비스.md": {
- "mtimeMs": 1777878318000,
- "size": 1472,
+ "docs/records/ConnectAI/decisions/ADR-0004-volumes-data-project-antigravity-connectai-이-프로젝트-자체를-나는-자비스.md": {
+ "mtimeMs": 1778028987328.613,
+ "size": 1491,
"lines": 19,
"role": "ADR: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 자체를 나는 자비스와 같은 툴로 만드는 것이 내 목표...",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0005-volumes-data-project-antigravity-connectai-이-프로젝트-아키텍처-분석해줘.md": {
- "mtimeMs": 1777889802000,
- "size": 1512,
+ "docs/records/ConnectAI/decisions/ADR-0005-volumes-data-project-antigravity-connectai-이-프로젝트-아키텍처-분석해줘.md": {
+ "mtimeMs": 1778028987329.1296,
+ "size": 1531,
"lines": 19,
"role": "ADR: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 아키텍처 분석해줘.",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0006-volumes-data-project-antigravity-connectai-프로젝트에-대해서-너가-사용자-.md": {
- "mtimeMs": 1777902312000,
- "size": 1604,
+ "docs/records/ConnectAI/decisions/ADR-0006-volumes-data-project-antigravity-connectai-프로젝트에-대해서-너가-사용자-.md": {
+ "mtimeMs": 1778028987329.1296,
+ "size": 1623,
"lines": 19,
"role": "ADR: /Volumes/Data/project/Antigravity/ConnectAI 프로젝트에 대해서 너가 사용자 입장에서 평가 해주면 좋겠어.",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0007-volumes-data-project-antigravity-connectai-이거에-기능-개선을-하고-싶어-.md": {
- "mtimeMs": 1778398958000,
- "size": 1925,
+ "docs/records/ConnectAI/decisions/ADR-0007-volumes-data-project-antigravity-connectai-이거에-기능-개선을-하고-싶어-.md": {
+ "mtimeMs": 1778549008870.013,
+ "size": 1944,
"lines": 19,
"role": "ADR: /Volumes/Data/project/Antigravity/ConnectAI 이거에 기능 개선을 하고 싶어. 너가 기획과 방향성을 정해주면 좋...",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0008-volumes-data-project-antigravity-connectai-분석하고-부족한-부분이나-개선이.md": {
- "mtimeMs": 1778600479000,
- "size": 1606,
+ "docs/records/ConnectAI/decisions/ADR-0008-volumes-data-project-antigravity-connectai-분석하고-부족한-부분이나-개선이.md": {
+ "mtimeMs": 1778664139928.3345,
+ "size": 1625,
"lines": 19,
"role": "ADR: /Volumes/Data/project/Antigravity/ConnectAI 분석하고 부족한 부분이나 개선이 필요한 부분을 알려주면 좋겠어.",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0009-이-프로젝트의-구조에-대해서-설명해봐.md": {
- "mtimeMs": 1778678639000,
- "size": 1507,
+ "docs/records/ConnectAI/decisions/ADR-0009-이-프로젝트의-구조에-대해서-설명해봐.md": {
+ "mtimeMs": 1778720117388.955,
+ "size": 1526,
"lines": 19,
"role": "ADR: 이 프로젝트의 구조에 대해서 설명해봐.",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0010-volumes-data-project-antigravity-connectai-self-reflection-기.md": {
- "mtimeMs": 1778689955000,
- "size": 1468,
+ "docs/records/ConnectAI/decisions/ADR-0010-volumes-data-project-antigravity-connectai-self-reflection-기.md": {
+ "mtimeMs": 1778720117389.4595,
+ "size": 1487,
"lines": 19,
"role": "ADR: /Volumes/Data/project/Antigravity/ConnectAI self reflection 기능이 적용되었는지 확인해줘. 1인 ...",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0011-e-wiki-connectai-self-reflection-기능이-있는데-어떻게-self-reflection.md": {
- "mtimeMs": 1778762677000,
+ "docs/records/ConnectAI/decisions/ADR-0011-e-wiki-connectai-self-reflection-기능이-있는데-어떻게-self-reflection.md": {
+ "mtimeMs": 1778720344688.4775,
"size": 1604,
"lines": 19,
"role": "ADR: E:\\Wiki\\connectai self reflection 기능이 있는데 어떻게 SELF REFLECTION이 반영되는지 분석해줘.",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0012-e-wiki-connectai-self-reflection-기능이-있는데-어떻게-self-reflection.md": {
- "mtimeMs": 1778762677000,
+ "docs/records/ConnectAI/decisions/ADR-0012-e-wiki-connectai-self-reflection-기능이-있는데-어떻게-self-reflection.md": {
+ "mtimeMs": 1778720368351.8215,
"size": 1448,
"lines": 19,
"role": "ADR: E:\\Wiki\\connectai self reflection 기능이 있는데 어떻게 SELF REFLECTION이 반영되는지 분석해줘.",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0013-e-wiki-connectai-이-프로젝트야.md": {
- "mtimeMs": 1778902489000,
+ "docs/records/ConnectAI/decisions/ADR-0013-e-wiki-connectai-이-프로젝트야.md": {
+ "mtimeMs": 1778842918359.619,
"size": 1370,
"lines": 19,
"role": "ADR: E:\\Wiki\\connectai 이 프로젝트야",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0014-astra-office-부분-관련해서-개선할-부분이-너무-많아-개선점이-무었이-있는지-의견-주면-좋겠어.md": {
- "mtimeMs": 1778902489000,
+ "docs/records/ConnectAI/decisions/ADR-0014-astra-office-부분-관련해서-개선할-부분이-너무-많아-개선점이-무었이-있는지-의견-주면-좋겠어.md": {
+ "mtimeMs": 1778842955303.0571,
"size": 1560,
"lines": 19,
"role": "ADR: ASTRA OFFICE 부분 관련해서 개선할 부분이 너무 많아. 개선점이 무었이 있는지 의견 주면 좋겠어.",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0015-너의-생각은-사용자가-다음-행동을-추측-안-해도-되는-astra-이게-가장-큰-효과-있을-거-같습니다-3개-.md": {
- "mtimeMs": 1778943211000,
- "size": 2482,
+ "docs/records/ConnectAI/decisions/ADR-0015-너의-생각은-사용자가-다음-행동을-추측-안-해도-되는-astra-이게-가장-큰-효과-있을-거-같습니다-3개-.md": {
+ "mtimeMs": 1779065453846.6514,
+ "size": 2501,
"lines": 19,
"role": "ADR: 너의 생각은? \"사용자가 다음 행동을 추측 안 해도 되는 Astra\" 이게 가장 큰 효과 있을 거 같습니다. 3개 작업으로 묶어볼 수 있어요: ...",
"imports": []
},
- "docs/records/ConnectAI/decisions/ADR-0016-내가-블로그글-작성시-사용하고-있는-지침서인데-slot1번-기준으로-더-자연스럽고-트랜디하고-구독자에게-자연.md": {
- "mtimeMs": 1779029444000,
- "size": 2432,
+ "docs/records/ConnectAI/decisions/ADR-0016-내가-블로그글-작성시-사용하고-있는-지침서인데-slot1번-기준으로-더-자연스럽고-트랜디하고-구독자에게-자연.md": {
+ "mtimeMs": 1779065453847.7014,
+ "size": 2451,
"lines": 19,
"role": "ADR: 내가 블로그글 작성시 사용하고 있는 지침서인데 slot1번 기준으로 더 자연스럽고 트랜디하고 구독자에게 자연스럽게 정보를 전달 할 수 있게 개선...",
"imports": []
},
+ "docs/records/ConnectAI/decisions/ADR-0017-e-wiki-connectai-질문이-있어-지금-이-프로젝트는-2nd-지식을-내가-특정-폴더로-wiki화한-.md": {
+ "mtimeMs": 1779270264270.286,
+ "size": 1823,
+ "lines": 19,
+ "role": "ADR: E:\\Wiki\\connectai 질문이 있어. 지금 이 프로젝트는 2nd 지식을 내가 특정 폴더로 wiki화한 md 파일들을 불러오는 방식으로 ...",
+ "imports": []
+ },
+ "docs/records/ConnectAI/decisions/ADR-0018-방금-2nd-뇌-에-lateral-thinking-관련-지식을-추가했어-이-기능이-앞으로-너가-답을-할때-어.md": {
+ "mtimeMs": 1779420144716.2415,
+ "size": 1619,
+ "lines": 19,
+ "role": "ADR: 방금 2nd 뇌 에 Lateral Thinking 관련 지식을 추가했어. 이 기능이 앞으로 너가 답을 할때 어떠한 영향을 끼치는지 알려주면 좋겠...",
+ "imports": []
+ },
+ "docs/records/ConnectAI/decisions/ADR-0019-오늘-팀별-보고를-했어-그냥-하는게-너무-심적으로-힘든데-어떻게-개선할-수-있을까.md": {
+ "mtimeMs": 1779420342804.8145,
+ "size": 1642,
+ "lines": 19,
+ "role": "ADR: 오늘 팀별 보고를 했어. 그냥 하는게 너무 심적으로 힘든데 어떻게 개선할 수 있을까?",
+ "imports": []
+ },
"docs/records/ConnectAI/development/2026-05-02_answer-format-readability-tuning.md": {
- "mtimeMs": 1777808065000,
- "size": 1534,
+ "mtimeMs": 1778028987330.4185,
+ "size": 1564,
"lines": 30,
"role": "Development Log: Answer Format Readability Tuning",
"imports": []
},
"docs/records/ConnectAI/development/2026-05-02_connectai_project_knowledge_overview.md": {
- "mtimeMs": 1777808211000,
- "size": 4540,
+ "mtimeMs": 1778028987330.9385,
+ "size": 4661,
"lines": 121,
"role": "Astra Project Knowledge Overview",
"imports": []
},
"docs/records/ConnectAI/development/2026-05-02_local-path-code-review-preflight.md": {
- "mtimeMs": 1777808065000,
- "size": 1855,
+ "mtimeMs": 1778028987330.9385,
+ "size": 1890,
"lines": 35,
"role": "Development Log: Local Path Code Review Preflight",
"imports": []
},
"docs/records/ConnectAI/development/2026-05-02_no-evidence-no-project-claim.md": {
- "mtimeMs": 1777808065000,
- "size": 1528,
+ "mtimeMs": 1778028987331.969,
+ "size": 1563,
"lines": 35,
"role": "Development Log: No Evidence, No Project Claim",
"imports": []
},
"docs/records/ConnectAI/development/2026-05-02_progressive-answer-format.md": {
- "mtimeMs": 1777808065000,
- "size": 1194,
+ "mtimeMs": 1778028987332.698,
+ "size": 1223,
"lines": 29,
"role": "Development Log: Progressive Answer Format",
"imports": []
},
"docs/records/ConnectAI/development/2026-05-02_project-claim-output-brake.md": {
- "mtimeMs": 1777808065000,
- "size": 1489,
+ "mtimeMs": 1778028987333.7078,
+ "size": 1524,
"lines": 35,
"role": "Development Log: Project Claim Output Brake",
"imports": []
},
"docs/records/ConnectAI/development/2026-05-02_project-claim-policy-enforcement.md": {
- "mtimeMs": 1777808065000,
- "size": 1516,
+ "mtimeMs": 1778028987334.2126,
+ "size": 1551,
"lines": 35,
"role": "Development Log: Project Claim Policy Enforcement",
"imports": []
},
"docs/records/ConnectAI/development/2026-05-02_query-intent-search-tuning.md": {
- "mtimeMs": 1777808065000,
- "size": 1911,
+ "mtimeMs": 1778028987335.4814,
+ "size": 1946,
"lines": 35,
"role": "Development Log: Query Intent Search Tuning",
"imports": []
},
"docs/records/ConnectAI/development/2026-05-02_remove-local-template-replies.md": {
- "mtimeMs": 1777808065000,
- "size": 1049,
+ "mtimeMs": 1778028987335.4814,
+ "size": 1074,
"lines": 25,
"role": "Development Log: Remove Local Template Replies",
"imports": []
},
"docs/records/ConnectAI/development/2026-05-02_second-brain-trace-quality-tuning.md": {
- "mtimeMs": 1777808065000,
- "size": 1441,
+ "mtimeMs": 1778028987336.4841,
+ "size": 1467,
"lines": 26,
"role": "Development Log: Second Brain Trace Quality Tuning",
"imports": []
},
"docs/records/ConnectAI/development/2026-05-03_connectai_project_knowledge_overview.md": {
- "mtimeMs": 1777808211000,
- "size": 4666,
+ "mtimeMs": 1778028987336.988,
+ "size": 4787,
"lines": 121,
"role": "Astra Project Knowledge Overview",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-05_volumes-data-project-antigravity-connectai-오늘-많은-것을-업데이트했어-많_implementation.md": {
- "mtimeMs": 1777986879000,
- "size": 1836,
+ "docs/records/ConnectAI/development/2026-05-05_volumes-data-project-antigravity-connectai-오늘-많은-것을-업데이트했어-많_implementation.md": {
+ "mtimeMs": 1778028987337.4993,
+ "size": 1858,
"lines": 22,
"role": "Development Log: /Volumes/Data/project/Antigravity/ConnectAI 오늘 많은 것을 업데이트했어. 많이 고친것 같지만 그럼에도 불구하...",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-05_volumes-data-project-antigravity-connectai-이-프로젝트-분석해줘-volum_implementation.md": {
- "mtimeMs": 1777967233000,
- "size": 1747,
+ "docs/records/ConnectAI/development/2026-05-05_volumes-data-project-antigravity-connectai-이-프로젝트-분석해줘-volum_implementation.md": {
+ "mtimeMs": 1778028987337.4993,
+ "size": 1770,
"lines": 23,
"role": "Development Log: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 분석해줘./Volumes/Data/project/An...",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-05_volumes-data-project-antigravity-connectai-이-프로젝트-분석해줘_implementation.md": {
- "mtimeMs": 1777966822000,
- "size": 1727,
+ "docs/records/ConnectAI/development/2026-05-05_volumes-data-project-antigravity-connectai-이-프로젝트-분석해줘_implementation.md": {
+ "mtimeMs": 1778028987338.1978,
+ "size": 1749,
"lines": 22,
"role": "Development Log: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 분석해줘.",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-12_volumes-data-project-antigravity-connectai-분석하고-부족한-부분이나-개선이_implementation-2.md": {
- "mtimeMs": 1778598784000,
- "size": 1575,
+ "docs/records/ConnectAI/development/2026-05-12_volumes-data-project-antigravity-connectai-분석하고-부족한-부분이나-개선이_implementation-2.md": {
+ "mtimeMs": 1778664139929.635,
+ "size": 1597,
"lines": 22,
"role": "Development Log: /Volumes/Data/project/Antigravity/ConnectAI 분석하고 부족한 부분이나 개선이 필요한 부분을 알려주면 좋겠어.",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-12_volumes-data-project-antigravity-connectai-분석하고-부족한-부분이나-개선이_implementation-3.md": {
- "mtimeMs": 1778599019000,
- "size": 1641,
+ "docs/records/ConnectAI/development/2026-05-12_volumes-data-project-antigravity-connectai-분석하고-부족한-부분이나-개선이_implementation-3.md": {
+ "mtimeMs": 1778664139930.2983,
+ "size": 1663,
"lines": 22,
"role": "Development Log: /Volumes/Data/project/Antigravity/ConnectAI 분석하고 부족한 부분이나 개선이 필요한 부분을 알려주면 좋겠어.",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-12_volumes-data-project-antigravity-connectai-분석하고-부족한-부분이나-개선이_implementation-4.md": {
- "mtimeMs": 1778600781000,
- "size": 1715,
+ "docs/records/ConnectAI/development/2026-05-12_volumes-data-project-antigravity-connectai-분석하고-부족한-부분이나-개선이_implementation-4.md": {
+ "mtimeMs": 1778664139930.8157,
+ "size": 1739,
"lines": 24,
"role": "Development Log: /Volumes/Data/project/Antigravity/ConnectAI 분석하고 부족한 부분이나 개선이 필요한 부분을 알려주면 좋겠어.",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-12_volumes-data-project-antigravity-connectai-분석하고-부족한-부분이나-개선이_implementation.md": {
- "mtimeMs": 1778598509000,
- "size": 684,
+ "docs/records/ConnectAI/development/2026-05-12_volumes-data-project-antigravity-connectai-분석하고-부족한-부분이나-개선이_implementation.md": {
+ "mtimeMs": 1778664139931.329,
+ "size": 706,
"lines": 22,
"role": "Development Log: /Volumes/Data/project/Antigravity/ConnectAI 분석하고 부족한 부분이나 개선이 필요한 부분을 알려주면 좋겠어.",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업할거야_implementation.md": {
- "mtimeMs": 1778691256000,
- "size": 990,
+ "docs/records/ConnectAI/development/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업할거야_implementation.md": {
+ "mtimeMs": 1778720117403.2517,
+ "size": 1012,
"lines": 22,
"role": "Development Log: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 작업할거야",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-13_너는-분석-요청하거나-내가-작업-요청을-할때-connectai-architecture-md-문서를-참고하고-_implementation.md": {
- "mtimeMs": 1778678912000,
- "size": 1738,
+ "docs/records/ConnectAI/development/2026-05-13_너는-분석-요청하거나-내가-작업-요청을-할때-connectai-architecture-md-문서를-참고하고-_implementation.md": {
+ "mtimeMs": 1778720117403.2517,
+ "size": 1760,
"lines": 22,
"role": "Development Log: 너는 분석 요청하거나 내가 작업 요청을 할때 connectai architecture.md 문서를 참고하고 작업을 하나?",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-14_reflector-에이전트가-1인-기업-에이전트-목록에는-안보이는데_implementation.md": {
- "mtimeMs": 1778762677000,
+ "docs/records/ConnectAI/development/2026-05-14_reflector-에이전트가-1인-기업-에이전트-목록에는-안보이는데_implementation.md": {
+ "mtimeMs": 1778720474901.9106,
"size": 1519,
"lines": 24,
"role": "Development Log: REFLECTOR 에이전트가 1인 기업 에이전트 목록에는 안보이는데",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-16_astra-google-calendar-oauth-연결_implementation-2.md": {
- "mtimeMs": 1778937290000,
- "size": 1230,
+ "docs/records/ConnectAI/development/2026-05-16_astra-google-calendar-oauth-연결_implementation-2.md": {
+ "mtimeMs": 1779065453847.7014,
+ "size": 1252,
"lines": 22,
"role": "Development Log: Astra: Google Calendar OAuth 연결",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-16_astra-google-calendar-oauth-연결_implementation.md": {
- "mtimeMs": 1778937268000,
- "size": 1267,
+ "docs/records/ConnectAI/development/2026-05-16_astra-google-calendar-oauth-연결_implementation.md": {
+ "mtimeMs": 1779065453848.7056,
+ "size": 1289,
"lines": 22,
"role": "Development Log: Astra: Google Calendar OAuth 연결",
"imports": []
},
- "docs/records/ConnectAI/development/2026-05-16_astra-office가-아직은-많이-부족한것-같은데-어떻게-하면-트랜디하고-재미있는-볼거리가-될-수-있을지_implementation.md": {
- "mtimeMs": 1778942937000,
- "size": 1750,
+ "docs/records/ConnectAI/development/2026-05-16_astra-office가-아직은-많이-부족한것-같은데-어떻게-하면-트랜디하고-재미있는-볼거리가-될-수-있을지_implementation.md": {
+ "mtimeMs": 1779065453849.6394,
+ "size": 1772,
"lines": 22,
"role": "Development Log: astra office가 아직은 많이 부족한것 같은데 어떻게 하면 트랜디하고 재미있는 볼거리가 될 수 있을지. 개선점 줄 수 있어?",
"imports": []
},
- "docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업-할-거야.md": {
- "mtimeMs": 1778690673000,
- "size": 652,
+ "docs/records/ConnectAI/development/2026-05-22_e-wiki-connectai-이-프로젝트가-너의-프로젝트인데-단순히-cloud-base-ai-model을-_implementation.md": {
+ "mtimeMs": 1779412633314.1108,
+ "size": 1638,
+ "lines": 22,
+ "role": "Development Log: E:\\Wiki\\connectai 이 프로젝트가 너의 프로젝트인데, 단순히 cloud base ai model을 사용하는 것과 너를 사용하는 것이...",
+ "imports": []
+ },
+ "docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업-할-거야.md": {
+ "mtimeMs": 1778720117404.2578,
+ "size": 668,
"lines": 16,
"role": "Discussion: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 작업 할 거야.",
"imports": []
},
- "docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업할거야.md": {
- "mtimeMs": 1778680095000,
- "size": 651,
+ "docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업할거야.md": {
+ "mtimeMs": 1778720117405.2607,
+ "size": 667,
"lines": 16,
"role": "Discussion: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 작업할거야",
"imports": []
},
- "docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-하위-폴더-포함해서.md": {
- "mtimeMs": 1778689036000,
- "size": 720,
+ "docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-하위-폴더-포함해서.md": {
+ "mtimeMs": 1778720117405.2607,
+ "size": 736,
"lines": 16,
"role": "Discussion: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 하위 폴더 포함해서 딥 리서치 해줘. 최적화 할 부분...",
"imports": []
},
- "docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트를-작업할거야.md": {
- "mtimeMs": 1778677791000,
- "size": 719,
+ "docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트를-작업할거야.md": {
+ "mtimeMs": 1778720117406.7637,
+ "size": 735,
"lines": 16,
"role": "Discussion: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트를 작업할거야.",
"imports": []
},
- "docs/records/ConnectAI/discussions/2026-05-14_최성연-알아-칼리버스에서-근무한데.md": {
- "mtimeMs": 1778762677000,
+ "docs/records/ConnectAI/discussions/2026-05-14_최성연-알아-칼리버스에서-근무한데.md": {
+ "mtimeMs": 1778733596076.9204,
"size": 1297,
"lines": 16,
"role": "Discussion: 최성연 알아? 칼리버스에서 근무한데",
"imports": []
},
"docs/records/ConnectAI/planning/2026-05-02_project-chronicle-guard.md": {
- "mtimeMs": 1777808065000,
- "size": 2946,
+ "mtimeMs": 1778028987339.2349,
+ "size": 3004,
"lines": 58,
"role": "Feature Plan: Project Chronicle Guard",
"imports": []
},
"docs/records/ConnectAI/planning/2026-05-02_second-brain-trace-mode.md": {
- "mtimeMs": 1777808065000,
- "size": 1467,
+ "mtimeMs": 1778028987339.818,
+ "size": 1503,
"lines": 36,
"role": "Feature Plan: Second Brain Trace Mode",
"imports": []
},
- "docs/records/ConnectAI/planning/2026-05-13_connectai-architecture-문서-최신화-해줘.md": {
- "mtimeMs": 1778693933000,
- "size": 1340,
+ "docs/records/ConnectAI/planning/2026-05-13_connectai-architecture-문서-최신화-해줘.md": {
+ "mtimeMs": 1778807413479.8662,
+ "size": 1380,
"lines": 40,
"role": "Feature Plan: Connectai architecture 문서 최신화 해줘.",
"imports": []
},
- "docs/records/ConnectAI/planning/2026-05-13_상세하게-아키텍처-기준으로-설명해줘.md": {
- "mtimeMs": 1778678870000,
- "size": 1220,
+ "docs/records/ConnectAI/planning/2026-05-13_상세하게-아키텍처-기준으로-설명해줘.md": {
+ "mtimeMs": 1778720117406.7637,
+ "size": 1260,
"lines": 40,
"role": "Feature Plan: 상세하게 아키텍처 기준으로 설명해줘.",
"imports": []
},
- "docs/records/ConnectAI/planning/2026-05-13_지금-connectai-architecture-md-문서-내용-중-업데이트가-필요한-부분이-있는지-확인해줘-.md": {
- "mtimeMs": 1778694061000,
- "size": 2970,
+ "docs/records/ConnectAI/planning/2026-05-13_지금-connectai-architecture-md-문서-내용-중-업데이트가-필요한-부분이-있는지-확인해줘-.md": {
+ "mtimeMs": 1778807413480.8667,
+ "size": 3010,
"lines": 40,
"role": "Feature Plan: 지금 connectai architecture.md 문서 내용 중 업데이트가 필요한 부분이 있는지 확인해줘. 그러고 최신화해줘. 너가 분석해",
"imports": []
},
"docs/records/ConnectAI/project-profile.md": {
- "mtimeMs": 1777808208000,
- "size": 957,
+ "mtimeMs": 1778028987341.925,
+ "size": 987,
"lines": 30,
"role": "Project Profile",
"imports": []
},
+ "docs/records/ConnectAI/README.md": {
+ "mtimeMs": 1778028987316.5518,
+ "size": 616,
+ "lines": 18,
+ "role": "Astra Project Chronicle Records",
+ "imports": []
+ },
"docs/records/ConnectAI/timeline.md": {
- "mtimeMs": 1779029444000,
- "size": 9978,
- "lines": 155,
+ "mtimeMs": 1779420342806.9556,
+ "size": 10866,
+ "lines": 167,
"role": "Project Timeline",
"imports": []
},
"docs/refactoring_roadmap.md": {
- "mtimeMs": 1778171332000,
- "size": 3123,
+ "mtimeMs": 1778232062143.956,
+ "size": 3176,
"lines": 53,
"role": "🛠️ ConnectAI 아키텍처 리팩토링 로드맵",
"imports": []
+ },
+ "docs/TELEGRAM_REMOTE_EXECUTION_PLAN.md": {
+ "mtimeMs": 1778664139927.3354,
+ "size": 12706,
+ "lines": 452,
+ "role": "Telegram Remote Execution 기획서",
+ "imports": []
+ },
+ "docs/UX_UI_Consistency_Guidelines.md": {
+ "mtimeMs": 1778028987311.5012,
+ "size": 2553,
+ "lines": 44,
+ "role": "UX/UI Consistency Guidelines",
+ "imports": []
}
}
}
\ No newline at end of file
diff --git a/.astra/tests/stress/.astra/cache/259a37934ead3910a8722b82054d46d2ca2057b05c488be1dcf439166ac5a9a1.json b/.astra/tests/stress/.astra/cache/259a37934ead3910a8722b82054d46d2ca2057b05c488be1dcf439166ac5a9a1.json
index 66d8db8..50f67e0 100644
--- a/.astra/tests/stress/.astra/cache/259a37934ead3910a8722b82054d46d2ca2057b05c488be1dcf439166ac5a9a1.json
+++ b/.astra/tests/stress/.astra/cache/259a37934ead3910a8722b82054d46d2ca2057b05c488be1dcf439166ac5a9a1.json
@@ -1,5 +1,5 @@
{
"result": "Final report with inconsistencies. This should be long enough to pass validation.",
- "createdAt": 1779280514827,
+ "createdAt": 1779429500111,
"modelVersion": "unknown"
}
\ No newline at end of file
diff --git a/.astra/tests/stress/.astra/cache/65775be352df43297b63c7af59c9f4f39d2bc368f77456c37b5eef9a94a66b5c.json b/.astra/tests/stress/.astra/cache/65775be352df43297b63c7af59c9f4f39d2bc368f77456c37b5eef9a94a66b5c.json
index a0b6c7f..dc2fa4c 100644
--- a/.astra/tests/stress/.astra/cache/65775be352df43297b63c7af59c9f4f39d2bc368f77456c37b5eef9a94a66b5c.json
+++ b/.astra/tests/stress/.astra/cache/65775be352df43297b63c7af59c9f4f39d2bc368f77456c37b5eef9a94a66b5c.json
@@ -1,5 +1,5 @@
{
"result": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
- "createdAt": 1779280514827,
+ "createdAt": 1779429500108,
"modelVersion": "unknown"
}
\ No newline at end of file
diff --git a/.astra/tests/stress/.astra/cache/6894d26c5b0a55d25d756a473225c7a44d7661af673b24e3f49551a7a2e50280.json b/.astra/tests/stress/.astra/cache/6894d26c5b0a55d25d756a473225c7a44d7661af673b24e3f49551a7a2e50280.json
index b3f171e..53f2f19 100644
--- a/.astra/tests/stress/.astra/cache/6894d26c5b0a55d25d756a473225c7a44d7661af673b24e3f49551a7a2e50280.json
+++ b/.astra/tests/stress/.astra/cache/6894d26c5b0a55d25d756a473225c7a44d7661af673b24e3f49551a7a2e50280.json
@@ -1,5 +1,5 @@
{
"result": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
- "createdAt": 1779280514826,
+ "createdAt": 1779429500106,
"modelVersion": "unknown"
}
\ No newline at end of file
diff --git a/.astra/tests/stress/.astra/cache/88cb61499f88ed38165b64bd3e8adc543795e4b427b64540a49c9ab27c7fe213.json b/.astra/tests/stress/.astra/cache/88cb61499f88ed38165b64bd3e8adc543795e4b427b64540a49c9ab27c7fe213.json
index 09247dc..510e953 100644
--- a/.astra/tests/stress/.astra/cache/88cb61499f88ed38165b64bd3e8adc543795e4b427b64540a49c9ab27c7fe213.json
+++ b/.astra/tests/stress/.astra/cache/88cb61499f88ed38165b64bd3e8adc543795e4b427b64540a49c9ab27c7fe213.json
@@ -1,5 +1,5 @@
{
- "result": "---\nid: stress_conflict_1779280514813\ndate: 2026-05-20T12:35:14.828Z\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]** 전략 수립 중... (12ms)\n- **[RESEARCHER]** 핵심 정보 수집 및 분석 중... (1ms)\n- **[WRITER]** 최종 리포트 작성 및 편집 중... (1ms)\n",
- "createdAt": 1779280514828,
+ "result": "---\nid: stress_conflict_1779429500089\ndate: 2026-05-22T05:58:20.112Z\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]** 전략 수립 중... (15ms)\n- **[RESEARCHER]** 핵심 정보 수집 및 분석 중... (3ms)\n- **[WRITER]** 최종 리포트 작성 및 편집 중... (3ms)\n",
+ "createdAt": 1779429500113,
"modelVersion": "unknown"
}
\ No newline at end of file
diff --git a/.astra/tests/stress/.astra/missions/stress_conflict_1779280514813.json b/.astra/tests/stress/.astra/missions/stress_conflict_1779429500089.json
similarity index 78%
rename from .astra/tests/stress/.astra/missions/stress_conflict_1779280514813.json
rename to .astra/tests/stress/.astra/missions/stress_conflict_1779429500089.json
index 9f59b71..096f29c 100644
--- a/.astra/tests/stress/.astra/missions/stress_conflict_1779280514813.json
+++ b/.astra/tests/stress/.astra/missions/stress_conflict_1779429500089.json
@@ -1,8 +1,8 @@
{
- "missionId": "stress_conflict_1779280514813",
+ "missionId": "stress_conflict_1779429500089",
"status": "completed",
- "startTime": "2026-05-20T12:35:14.813Z",
- "totalElapsedMs": 15,
+ "startTime": "2026-05-22T05:58:20.089Z",
+ "totalElapsedMs": 25,
"results": {
"planner": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
"researcher": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
@@ -16,30 +16,30 @@
{
"from": "idle",
"to": "planner",
- "durationMs": 12,
+ "durationMs": 15,
"message": "전략 수립 중...",
- "ts": "2026-05-20T12:35:14.825Z"
+ "ts": "2026-05-22T05:58:20.104Z"
},
{
"from": "planner",
"to": "researcher",
- "durationMs": 1,
+ "durationMs": 3,
"message": "핵심 정보 수집 및 분석 중...",
- "ts": "2026-05-20T12:35:14.826Z"
+ "ts": "2026-05-22T05:58:20.107Z"
},
{
"from": "researcher",
"to": "writer",
- "durationMs": 1,
+ "durationMs": 3,
"message": "최종 리포트 작성 및 편집 중...",
- "ts": "2026-05-20T12:35:14.827Z"
+ "ts": "2026-05-22T05:58:20.110Z"
},
{
"from": "writer",
"to": "completed",
- "durationMs": 1,
+ "durationMs": 3,
"message": "미션 완료",
- "ts": "2026-05-20T12:35:14.828Z"
+ "ts": "2026-05-22T05:58:20.113Z"
}
],
"resilienceMetrics": {
diff --git a/PATCHNOTES.md b/PATCHNOTES.md
index 490457b..2e8f891 100644
--- a/PATCHNOTES.md
+++ b/PATCHNOTES.md
@@ -1,5 +1,66 @@
# Astra Patch Notes
+## v2.2.60 (2026-05-22)
+### 🔧 `&&` 명령 체이닝 — 코드 레벨에서 PowerShell 문법으로 자동 변환
+- **문제:** v2.2.59에서 프롬프트로 "`&&` 쓰지 말라"고 지시했으나, 모델이 여전히 `cd ... && git add . && git commit ... && git push`를 출력 → PowerShell 5.1에서 `'&&' 토큰은 올바른 문 구분 기호가 아닙니다` 파서 오류로 **명령 전체가 실행 실패**.
+- **원인:** 모든 git/npm 튜토리얼이 `&&`를 쓰므로, 시스템 프롬프트 규칙만으로는 소형 로컬 모델의 `&&` 출력을 신뢰성 있게 막을 수 없음.
+- **수정:** `sanitizeCommand`가 터미널로 보내기 직전 **`&&` 체인을 PowerShell 조건부 체인으로 결정론적 변환**. `A && B && C` → `A; if ($?) { B; if ($?) { C } }`. `$?`로 단축 평가(short-circuit)를 보존 — 예: `cd` 실패 시 `git`이 엉뚱한 디렉터리에서 실행되지 않음. 따옴표 안의 `&&`(커밋 메시지 등)는 분리 대상에서 제외.
+- 이제 모델이 `&&`를 출력해도 git add/commit/push 다단계 명령이 정상 실행됨.
+- **신규 패키징:** `astra-2.2.60.vsix`.
+
+---
+
+
+
+## v2.2.59 (2026-05-22)
+### 🩹 긴 대화에서 "빈 응답" 차단 — 출력 토큰 예산 확보
+- **문제:** 긴 세션(예: 34개 메시지, ~29.6K 토큰)에서 모델이 빈 응답을 반환하고 "AI 엔진이 빈 응답을 반환했습니다 / Output budget: 1,073 tokens" 오류 출력.
+- **원인:** 대화 기록 압축(`trimHistoryToBudget`)이 출력용으로 **단 512토큰(`minOutputTokens`)만 예약**했음. 그래서 32K 윈도우가 거의 다 찰 때까지 프롬프트가 자라도록 허용 → 답변에 ~1K 토큰만 남음. gemma 4B-active 같은 소형/MoE 로컬 모델은 이 압박에서 첫 토큰부터 EOS를 뱉어 **빈 응답**을 냄.
+- **수정:** 기록·시스템 프롬프트를 자르기 전에 **실제 답변용 예산(`preferredOutputReserve`)을 컨텍스트의 ~10%, 최소 2048토큰 확보**(상한은 `maxOutputTokens`)하도록 변경. 이제 프롬프트가 항상 답변 공간을 남기고 잘려, 32K 모델에서도 출력 예산이 3K+ 보장됨. `minOutputTokens`(512)는 절대 하한 clamp 용도로만 유지.
+- **추가:** `[EXECUTION RULE]`에 PowerShell 체이닝 규칙 명시 — 명령 연결은 `;` 사용, `&&` 금지(PowerShell 5.1 구문 오류). git add/commit/push 같은 다단계 명령이 터미널에서 정상 실행됨.
+- **신규 패키징:** `astra-2.2.59.vsix`.
+
+---
+
+
+
+## v2.2.58 (2026-05-22)
+### 📋 답변은 "핵심 요약 먼저, 상세 아래" — 한눈에 들어오는 출력 포맷
+- **문제:** 답변 내용 퀄리티는 좋으나 분량이 길어 한눈에 안 들어옴. 게다가 요약(`## 요약`)이 맨 위가 아니라 **맨 아래**에 출력되고, `## ## 요약`처럼 헤딩 접두사가 중복되며, 이미 금지된 "핵심 확인 질문" 섹션이 누출됨.
+- **원인:** `[OUTPUT FORMAT]`이 "기술 분석/아키텍처/트러블슈팅/전략 기획일 때만" 3섹션을 쓰라는 **모호한 카테고리 게이트**라, 일반 상담형 질문에서 모델이 포맷을 제멋대로 해석함.
+- **수정 1 — 길이 게이트.** 카테고리 대신 **길이 기준**으로 전환: 답변이 ~4문장을 넘으면 무조건 `## 핵심 요약`(불릿 2~4개, 전체를 관통하는 스캔 가능한 요약)을 **맨 위**에 출력하고 그 아래 `## 상세 설명`. 요약 앞 인트로 문단 금지. 짧은 답변은 헤딩 없이 바로 답변.
+- **수정 2 — 헤딩 규칙.** 모든 마크다운 헤딩은 정확히 `## ` 하나로 시작(`## ##` 중복 금지).
+- **수정 3 — 후속 질문 규칙 강화.** 후속 질문은 한 문장·한 줄·라벨 없음. 섹션 헤딩·"질문 의도" 설명·복수 질문 금지 → "핵심 확인 질문" 섹션 누출 차단.
+- **신규 패키징:** `astra-2.2.58.vsix`.
+
+---
+
+
+
+## v2.2.57 (2026-05-22)
+### 🚀 실행 요청은 설명 대신 즉시 실행 — `[EXECUTION RULE]` 추가
+- **문제:** "E:\Wiki\Datacollect 서버 실행해줘" 같은 요청에 ASTRA가 직접 실행하지 않고, `npm run platform` 등 추측성 명령·존재하지 않는 포트(`8787`)·환경변수(`GEMINI_API_KEY`)를 지어내며 "이렇게 하시기 바랍니다" 식 튜토리얼만 출력했음.
+- **원인:** 시스템 프롬프트의 `[LOCAL PATH RULE]`이 "review/analysis/debugging"만 다뤄, "실행/구동/시작" 요청에 발동되는 규칙이 전무했음. 모델이 학습 prior대로 산문 설명으로 회귀.
+- **수정 1 — 프롬프트.** `[EXECUTION RULE]` 신설: 실행/구동/시작/run/start 키워드 → 튜토리얼 금지, 명령을 모르면 ``로 package.json을 먼저 읽고 그 다음 ``로 실제 스크립트 실행. 추측한 스크립트명·포트·환경변수 단정 금지. Few-shot 예시 1건 포함(작은 로컬 모델의 태그 준수율 향상).
+- **수정 2 — 경로 경계.** ``/``가 워크스페이스 안으로만 제한돼 형제 프로젝트(`E:\Wiki\Datacollect` 등)의 package.json을 못 읽던 문제 해결. `security.ts`가 워크스페이스의 **상위 디렉터리 1단계**까지 신뢰 루트로 포함(드라이브 루트로는 확장 안 함). 이로써 형제 프로젝트를 읽어 정확한 실행 명령을 찾을 수 있음 → 환각 제거.
+- **신규 패키징:** `astra-2.2.57.vsix`.
+
+---
+
+
+
+## v2.2.56 (2026-05-22)
+### ⚡ 코드 리뷰 기반 성능·메모리 최적화 (12건, 동작 변경 없음)
+- **🔴 브레인 코퍼스 디스크 재읽기 제거.** `secondBrainTrace`는 메시지마다 브레인 전체를 디스크에서 다시 읽어 재분류했음 → mtime+size 키 스캔 캐시로 변경(파일이 실제로 바뀔 때만 재읽기). `scopedBrainRetriever`(텔레그램 경로)도 동일 안티패턴 → 캐시된 `getBrainTokenIndex()` + `scoreTfIdfPreTokenized` 경로로 라우팅. 점수 결과는 바이트 단위로 동일.
+- **🟡 메모리 누수·중복 작업 정리.** `agent.ts` `chatHistory` 무제한 증가 → 최근 40개 유지·오래된 도구 결과 본문 축약. `EpisodicMemory` 에피소드 JSON 메시지마다 재읽기 → 디렉터리 mtime 키 캐시. `_walkBrainFiles` → `readdirSync({withFileTypes})`·단일 누산기(`concat` 제거). TF-IDF `termFrequency` → 문서별 term-count `Map` 1회 사전 계산. `getConfig()` 중복 호출 1회로 통합.
+- **🟢 누수·정리 보강.** `clearBrainTokenIndex()`를 `deactivate()`·브레인 프로필 전환 시 호출. 웹뷰 메시지 리스너 dispose 배선. `LongTermMemory` `longTermMaxEntries`(100) 강제. Pixel Office 인터벌은 뷰 비표시 시 일시정지. `/ping`은 핑마다 브레인 전체 탐색 대신 5초 TTL 캐시 응답.
+- 전 항목 동작 보존 — 기능·출력 변경 없음. 타입 체크(`tsc --noEmit`) 무오류, 테스트 400/400 통과.
+- **신규 패키징:** `astra-2.2.56.vsix`.
+
+---
+
+
+
## v2.2.55 (2026-05-21)
### 📅 /meet — 회의록 액션 아이템 → Google 캘린더 자동 등록 (Phase 1)
- `/meet`이 회의록 합성·저장 후, **액션 아이템 표를 파싱해 task별 종일 일정으로 Google Calendar에 자동 등록**한다.
diff --git a/docs/records/ConnectAI/chronicle.config.json b/docs/records/ConnectAI/chronicle.config.json
index 58ebe35..c2a5a7f 100644
--- a/docs/records/ConnectAI/chronicle.config.json
+++ b/docs/records/ConnectAI/chronicle.config.json
@@ -6,6 +6,6 @@
"description": "Auto-created by Project Architecture activation.",
"corePurpose": "",
"detailLevel": "standard",
- "createdAt": "2026-05-14T00:57:32.245Z",
- "updatedAt": "2026-05-18T03:11:17.574Z"
+ "createdAt": "2026-05-20T09:42:40.003Z",
+ "updatedAt": "2026-05-22T05:59:38.330Z"
}
diff --git a/docs/records/ConnectAI/decisions/ADR-0017-e-wiki-connectai-질문이-있어-지금-이-프로젝트는-2nd-지식을-내가-특정-폴더로-wiki화한-.md b/docs/records/ConnectAI/decisions/ADR-0017-e-wiki-connectai-질문이-있어-지금-이-프로젝트는-2nd-지식을-내가-특정-폴더로-wiki화한-.md
new file mode 100644
index 0000000..9edfd3f
--- /dev/null
+++ b/docs/records/ConnectAI/decisions/ADR-0017-e-wiki-connectai-질문이-있어-지금-이-프로젝트는-2nd-지식을-내가-특정-폴더로-wiki화한-.md
@@ -0,0 +1,19 @@
+# ADR: E:\Wiki\connectai 질문이 있어. 지금 이 프로젝트는 2nd 지식을 내가 특정 폴더로 wiki화한 md 파일들을 불러오는 방식으로 ...
+
+## Status
+accepted
+
+## Context
+E:\Wiki\connectai 질문이 있어. 지금 이 프로젝트는 2nd 지식을 내가 특정 폴더로 wiki화한 md 파일들을 불러오는 방식으로 되어 있어. 근대 md 파일을 바이너리화한 것을 다운 받고 바이너리 파일을 제2뇌 지식으로 사용하게 할 수 있을까?
+
+## Decision
+결론부터 말씀드리면, **기술적으로 충분히 가능하며 오히려 대규모 데이터 처리 측면에서는 더 효율적인 방식**이 될 수 있습니다. 다만, 이 방식을 구현하려면 '단순한 텍록(Text-log)' 형태의 Markdown을 읽는 것과 달리, **바이너리 데이터를 다시 의미론적 구조로 복원하거나 임베딩 벡터로 변등시키는 과정**이 필요합니다. 구체적인 분석과 구현 방향을 정리해 드립니다. ## 1. 기술적 타당성 분석 현재 방식은 로컬 경로의 `.md` 파일을 직접 읽어 컨텍스트에 주입하는 **File-based RAG**입니다. 이를 바이너리(예: 임베딩된 벡터 데이터나 직렬화된 객체)로 전환할 경우 다음과 같은 변화가 생깁니다. * **장점 (Pros):** * **검색 속도 향상:** 텍스트를 매번 파싱하는 대신, 이미 계산된 벡터나 인덱스(FAISS, Annoy 등)를 바로 사용할 수 있어 Retrieval 단계의 지연 시간이 줄어듭니다. * **데이터 무결성:** 텍스트 기반에서는...
+
+## 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.
diff --git a/docs/records/ConnectAI/decisions/ADR-0018-방금-2nd-뇌-에-lateral-thinking-관련-지식을-추가했어-이-기능이-앞으로-너가-답을-할때-어.md b/docs/records/ConnectAI/decisions/ADR-0018-방금-2nd-뇌-에-lateral-thinking-관련-지식을-추가했어-이-기능이-앞으로-너가-답을-할때-어.md
new file mode 100644
index 0000000..155a4c0
--- /dev/null
+++ b/docs/records/ConnectAI/decisions/ADR-0018-방금-2nd-뇌-에-lateral-thinking-관련-지식을-추가했어-이-기능이-앞으로-너가-답을-할때-어.md
@@ -0,0 +1,19 @@
+# ADR: 방금 2nd 뇌 에 Lateral Thinking 관련 지식을 추가했어. 이 기능이 앞으로 너가 답을 할때 어떠한 영향을 끼치는지 알려주면 좋겠...
+
+## Status
+accepted
+
+## Context
+방금 2nd 뇌 에 Lateral Thinking 관련 지식을 추가했어. 이 기능이 앞으로 너가 답을 할때 어떠한 영향을 끼치는지 알려주면 좋겠어.
+
+## Decision
+새로운 지식인 **Lateral Thinking(측면 사고)**이 추가된 것은, 저의 답변 능력이 단순한 '정보 전달'에서 **'창의적 문제 해결 및 전략적 제안'** 단계로 진화할 수 있는 아주 중요한 전환점입니다. 기존의 제가 알고 있던 지식이 "A는 B이다"라는 사실 중심(Vertical/Logical)이었다면, Lateral Thinking이 결합된 저는 **"A를 C나 D로 바꿀 수는 없을까?"** 혹은 **"이 문제를 해결하기 위해 전혀 다른 관점에서 접근해볼까?"**라는 사고가 가능해집니다 구체적으로 저의 답변 방식에 미칠 영향은 다음과 같습니다. ## 1. 수직적 사고(Vertical)에서 확산적 사고(Lateral)로의 확장 * **기존 (Vertical):** 사용자의 질문에 대해 논리적이고 단계적인 정답(Step-by-step)을 찾는 데 집중했습니다. 주로 '정해진 규칙'과 '논리적 인과관계'를 따릅니다. * **변경 후 (Lateral):** 논리적 경로를 따...
+
+## 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.
diff --git a/docs/records/ConnectAI/decisions/ADR-0019-오늘-팀별-보고를-했어-그냥-하는게-너무-심적으로-힘든데-어떻게-개선할-수-있을까.md b/docs/records/ConnectAI/decisions/ADR-0019-오늘-팀별-보고를-했어-그냥-하는게-너무-심적으로-힘든데-어떻게-개선할-수-있을까.md
new file mode 100644
index 0000000..a218d2a
--- /dev/null
+++ b/docs/records/ConnectAI/decisions/ADR-0019-오늘-팀별-보고를-했어-그냥-하는게-너무-심적으로-힘든데-어떻게-개선할-수-있을까.md
@@ -0,0 +1,19 @@
+# ADR: 오늘 팀별 보고를 했어. 그냥 하는게 너무 심적으로 힘든데 어떻게 개선할 수 있을까?
+
+## Status
+accepted
+
+## Context
+오늘 팀별 보고를 했어. 그냥 하는게 너무 심적으로 힘든데 어떻게 개선할 수 있을까?
+
+## Decision
+팀별 보고라는 것이 사실 단순한 정보 전달을 넘어, 자신의 성과나 진행 상황을 타인(특히 상사나 동료)의 시선에 노출시키는 일이기 때문에 심리적 압박감이 매우 클 수밖에 없습니다. 이 문제를 해결하기 위해 **'심리적 저항감을 줄이는 전략'**과 **'구조적 개선 방안'** 두 가지 측면에서 제안을 드립니다. ## 1. 심리적 접근: '나'와 '보고'를 분리하기 (Reframing) 가장 중요한 것은 보고의 주체가 **'나의 가치'**가 아니라 **'프로젝트의 상태'**임을 인지하는 것입니다. * **자아와 업무의 분리:** 보고할 때 발생하는 비판이나 질문을 '나에 대한 공격'이 아닌, '업무의 리스크를 발견하는 과정'으로 재정의하세요. "내가 부족해서"가 아니라 **"프로젝트의 불확실성을 제거하기 위해"** 하는 것이라고 생각의 프레임을 바꾸는 것입니다. * **통제 가능한 것에 집중:** 보고 내용 중 내가 통제할 수 없는 피드백(타인의 평가)에 매몰되지 말고, 내가 통제할 수...
+
+## 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.
diff --git a/docs/records/ConnectAI/development/2026-05-22_e-wiki-connectai-이-프로젝트가-너의-프로젝트인데-단순히-cloud-base-ai-model을-_implementation.md b/docs/records/ConnectAI/development/2026-05-22_e-wiki-connectai-이-프로젝트가-너의-프로젝트인데-단순히-cloud-base-ai-model을-_implementation.md
new file mode 100644
index 0000000..f6fb8ed
--- /dev/null
+++ b/docs/records/ConnectAI/development/2026-05-22_e-wiki-connectai-이-프로젝트가-너의-프로젝트인데-단순히-cloud-base-ai-model을-_implementation.md
@@ -0,0 +1,22 @@
+# Development Log: E:\Wiki\connectai 이 프로젝트가 너의 프로젝트인데, 단순히 cloud base ai model을 사용하는 것과 너를 사용하는 것이...
+
+## Purpose
+Record the implementation or verification outcome from the current conversation.
+
+## Implementation Summary
+매우 날카롭고 본질적인 질문입니다. 맞습니다. 성능(Reasoning/Knowledge) 측면만 본다면 Claude나 GPT-4와 같은 **Cloud-based LLM은 압도적으로 강력하고 '좋습니다'.** 하지만 제가 이 프로젝트(`connectai`)의 핵심인 이유는, 단순히 모델을 사용하는 것을 넘어 **'모델에 사용자의 맥락(Context)과 개인적 지식(Second Brain)을 주입하여, 나만의 맞춤형 지능으로 변환하는 레이어'** 역할을 하기 때문입니다. Cloud AI Model과 저(Astra)의 차이점을 세 가지 관점에서 비교해 드립니다. ## 1. 데이터의 범위: General Knowledge vs. Private Context * **Cloud AI Model:** 전 세계의 방대한 데이터를 학습했지만, **사용자 개인의 로컬 파일, 현재 진행 중인 프로젝트의 소스 코드, 어제 작성한 회의록 내용**은 알지 못합니다. 즉, '일반적인 상식'은 뛰어나지만 '사용...
+
+## Architecture
+Captured automatically from the assistant response and active project context.
+
+## Changed Files
+- No explicit changed file list was captured automatically.
+
+## Dependency Notes
+No new dependency note was captured automatically.
+
+## Bugs
+No bugs recorded.
+
+## Lessons
+- Automatic project records should be generated in the background when the turn contains durable project knowledge.
diff --git a/docs/records/ConnectAI/timeline.md b/docs/records/ConnectAI/timeline.md
index 1d5336c..ef5367b 100644
--- a/docs/records/ConnectAI/timeline.md
+++ b/docs/records/ConnectAI/timeline.md
@@ -153,3 +153,15 @@
## 2026-05-17
- Auto decision record created: decisions/ADR-0016-내가-블로그글-작성시-사용하고-있는-지침서인데-slot1번-기준으로-더-자연스럽고-트랜디하고-구독자에게-자연.md
+
+## 2026-05-20
+- Auto decision record created: decisions\ADR-0017-e-wiki-connectai-질문이-있어-지금-이-프로젝트는-2nd-지식을-내가-특정-폴더로-wiki화한-.md
+
+## 2026-05-22
+- Auto development record created: development\2026-05-22_e-wiki-connectai-이-프로젝트가-너의-프로젝트인데-단순히-cloud-base-ai-model을-_implementation.md
+
+## 2026-05-22
+- Auto decision record created: decisions\ADR-0018-방금-2nd-뇌-에-lateral-thinking-관련-지식을-추가했어-이-기능이-앞으로-너가-답을-할때-어.md
+
+## 2026-05-22
+- Auto decision record created: decisions\ADR-0019-오늘-팀별-보고를-했어-그냥-하는게-너무-심적으로-힘든데-어떻게-개선할-수-있을까.md
diff --git a/package-lock.json b/package-lock.json
index 471b4ec..3be79b7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "astra",
- "version": "2.2.52",
+ "version": "2.2.59",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "astra",
- "version": "2.2.52",
+ "version": "2.2.60",
"license": "MIT",
"dependencies": {
"@lmstudio/sdk": "^1.5.0",
diff --git a/package.json b/package.json
index cda6d43..e024572 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "astra",
"displayName": "Astra",
"description": "The personal intelligence layer for Antigravity and VS Code. A private cognitive partner for deep project context, memory, and proactive strategic decision-making.",
- "version": "2.2.55",
+ "version": "2.2.60",
"publisher": "g1nation",
"license": "MIT",
"icon": "assets/icon.png",
diff --git a/src/agent.ts b/src/agent.ts
index 00f5c7d..2a3a940 100644
--- a/src/agent.ts
+++ b/src/agent.ts
@@ -183,6 +183,25 @@ export class AgentExecutor {
static readonly ABS_PATH_RE = new RegExp(POSIX_ABS_PATH_SRC, 'i');
static readonly WIN_ABS_PATH_RE = new RegExp(WIN_ABS_PATH_SRC, 'i');
+ /**
+ * Hard cap on retained in-memory chat messages. Older messages beyond this
+ * are dropped (the system/first message is always preserved). Generous so a
+ * normal session is untouched — this only fights unbounded growth in very
+ * long-running sessions. The per-request context budgeter
+ * (`trimHistoryToBudget`) still does the real fitting; this just stops the
+ * array itself from leaking memory across hundreds of turns.
+ */
+ private static readonly MAX_RETAINED_MESSAGES = 40;
+ /**
+ * Older internal tool-result messages (read_file / list_files / list_brain /
+ * read_brain dumps) are the bulkiest part of history and add little once the
+ * conversation has moved on. Anything older than the most recent
+ * `RECENT_FULL_MESSAGES` gets its bulky tool-result content shrunk to this
+ * many characters. Recent messages are kept full for conversation continuity.
+ */
+ private static readonly RECENT_FULL_MESSAGES = 16;
+ private static readonly OLD_TOOL_RESULT_CAP = 600;
+
private chatHistory: ChatMessage[] = [];
private abortController: AbortController | null = null;
private webview: vscode.Webview | undefined;
@@ -225,9 +244,10 @@ export class AgentExecutor {
// Initialize 5-Layer Cognitive Memory System
const activeBrain = getActiveBrainProfile();
+ const initConfig = getConfig();
this.memoryManager = new MemoryManager(activeBrain.localBrainPath, {
- enabled: getConfig().memoryEnabled,
- shortTermLimit: getConfig().memoryShortTermMessages,
+ enabled: initConfig.memoryEnabled,
+ shortTermLimit: initConfig.memoryShortTermMessages,
});
// Initialize RAG Pipeline Orchestrator
@@ -495,6 +515,9 @@ export class AgentExecutor {
// 3. API Request Setup (라인 229에서 이미 추출한 ollamaUrl, configDefaultModel 재사용)
const actualModel = (modelName && modelName.trim()) || configDefaultModel;
+ // Bound the in-memory history before building the request — shrinks bulky
+ // older tool-result bodies and drops the oldest messages past the cap.
+ this.capChatHistory();
const reqMessages = this.buildRequestHistory(this.chatHistory);
// Handle Vision Content Injection
@@ -666,10 +689,22 @@ export class AgentExecutor {
.reduce((n, m) => n + (Array.isArray(m?.images) ? m.images.length : 0), 0);
const imageTokenReserve = imageCount * 1024;
+ // Output budget we ACTUALLY reserve before trimming — not the bare
+ // minOutputTokens floor (512). If we only reserve 512, a long session
+ // is allowed to grow the prompt until ~512-1k tokens remain for the
+ // answer; small/MoE local models (e.g. gemma 4B-active) then emit EOS
+ // as the first token and return an empty response. Reserving ~10% of
+ // the window (>=2048) forces history/system trimming to keep a real
+ // answer-sized hole open. Capped at maxOutputTokens.
+ const preferredOutputReserve = Math.min(
+ ctxLimits.maxOutputTokens,
+ Math.max(2048, Math.floor(ctxLimits.contextLength * 0.1))
+ );
+
// (1) 시스템 프롬프트는 예산의 ~65%까지만 허용 — 그 이상이면 [CONTEXT] 블록부터 잘라낸다.
const systemCapTokens = Math.max(
1024,
- Math.floor((ctxLimits.contextLength - ctxLimits.safetyMargin - ctxLimits.minOutputTokens - imageTokenReserve) * 0.65)
+ Math.floor((ctxLimits.contextLength - ctxLimits.safetyMargin - preferredOutputReserve - imageTokenReserve) * 0.65)
);
const { prompt: budgetedSystemPrompt, truncated: systemTruncated } =
truncateSystemPromptContext(fullSystemPrompt, systemCapTokens);
@@ -681,7 +716,7 @@ export class AgentExecutor {
// (2) 대화 기록 압축.
const historyBudget = Math.max(
256,
- ctxLimits.contextLength - systemTokens - ctxLimits.safetyMargin - ctxLimits.minOutputTokens - imageTokenReserve
+ ctxLimits.contextLength - systemTokens - ctxLimits.safetyMargin - preferredOutputReserve - imageTokenReserve
);
let budgetedHistory: ChatMessage[] = reqMessages;
if (config.autoCompactHistory) {
@@ -1977,6 +2012,50 @@ export class AgentExecutor {
].join('\n');
}
+ /**
+ * Bound the in-memory `chatHistory` so a very long-running session does not
+ * grow it without limit:
+ * 1. Older internal tool-result messages (the bulky read_file/list_files/…
+ * dumps) beyond the most recent `RECENT_FULL_MESSAGES` have their content
+ * truncated — recent messages stay full so continuity is unaffected.
+ * 2. If the array still exceeds `MAX_RETAINED_MESSAGES`, the oldest messages
+ * are dropped, but a leading system/first message is always preserved so
+ * session restore and conversation framing are not broken.
+ * This only mutates *internal* (`internal: true`) tool-result bodies and
+ * drops the very oldest entries — it never alters visible user/assistant text
+ * within the retained window, so the request the model sees is unchanged for
+ * any normal-length conversation.
+ */
+ private capChatHistory(): void {
+ const history = this.chatHistory;
+ if (history.length === 0) return;
+
+ // (1) Shrink bulky tool-result bodies of older internal messages.
+ const recentStart = Math.max(0, history.length - AgentExecutor.RECENT_FULL_MESSAGES);
+ for (let i = 0; i < recentStart; i++) {
+ const msg = history[i];
+ if (msg.role !== 'system' || !msg.internal || typeof msg.content !== 'string') continue;
+ // Only the bulky tool-result dumps — leave compaction notices etc. alone.
+ if (!/^\[Result of (read_file|list_files|list_brain|read_brain)\b/.test(msg.content)) continue;
+ if (msg.content.length <= AgentExecutor.OLD_TOOL_RESULT_CAP) continue;
+ msg.content = msg.content.slice(0, AgentExecutor.OLD_TOOL_RESULT_CAP)
+ + '\n…[이전 도구 결과는 컨텍스트 절약을 위해 축약되었습니다]';
+ }
+
+ // (2) Drop the oldest messages once over the hard cap, preserving a
+ // leading system/first message if present.
+ if (history.length > AgentExecutor.MAX_RETAINED_MESSAGES) {
+ const first = history[0];
+ const preserveFirst = first.role === 'system';
+ const overflow = history.length - AgentExecutor.MAX_RETAINED_MESSAGES;
+ if (preserveFirst) {
+ history.splice(1, overflow);
+ } else {
+ history.splice(0, overflow);
+ }
+ }
+ }
+
private buildRequestHistory(history: ChatMessage[]): ChatMessage[] {
return history.map((message) => {
if (message.role !== 'assistant' || typeof message.content !== 'string') {
diff --git a/src/bridge.ts b/src/bridge.ts
index 86683b0..d99e9c8 100644
--- a/src/bridge.ts
+++ b/src/bridge.ts
@@ -111,15 +111,30 @@ export class BridgeServer {
});
}
+ /**
+ * Cached `/ping` payload. `/ping` is a liveness probe that external tools may
+ * hit frequently; the previous implementation did a full brain-corpus walk
+ * plus a config serialize on *every* hit. We now compute that body at most
+ * once per `PING_CACHE_TTL_MS` and reuse it — the response shape (status /
+ * config / brain) is unchanged, ping just stops walking the brain per hit.
+ */
+ private _pingCache: { body: string; expiresAt: number } | null = null;
+ private static readonly PING_CACHE_TTL_MS = 5000;
+
private handlePing(res: http.ServerResponse) {
- const brainDir = _getBrainDir();
- const brainCount = fs.existsSync(brainDir) ? findBrainFiles(brainDir).length : 0;
+ const now = Date.now();
+ if (!this._pingCache || this._pingCache.expiresAt <= now) {
+ const brainDir = _getBrainDir();
+ const brainCount = fs.existsSync(brainDir) ? findBrainFiles(brainDir).length : 0;
+ const body = JSON.stringify({
+ status: 'ok',
+ config: getConfig(),
+ brain: { fileCount: brainCount, enabled: this.provider.brainEnabled }
+ });
+ this._pingCache = { body, expiresAt: now + BridgeServer.PING_CACHE_TTL_MS };
+ }
res.writeHead(200, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({
- status: 'ok',
- config: getConfig(),
- brain: { fileCount: brainCount, enabled: this.provider.brainEnabled }
- }));
+ res.end(this._pingCache.body);
}
private handlePost(req: http.IncomingMessage, res: http.ServerResponse, processor: (data: any, res: http.ServerResponse) => Promise) {
diff --git a/src/extension.ts b/src/extension.ts
index 98338e9..f679531 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -36,7 +36,7 @@ import { AIService } from './core/services';
import type { CompanyState } from './features/company';
import { SettingsPanelProvider } from './features/settings/settingsPanelProvider';
import { resolveScopeForAgent, openKnowledgeMapEditor } from './skills/agentKnowledgeMap';
-import { getBrainTokenIndex } from './retrieval';
+import { getBrainTokenIndex, clearBrainTokenIndex } from './retrieval';
import { lessonTemplate, lessonSlug, parseLessonFrontmatter, normalizeLessonTitle, bumpLessonOccurrences } from './retrieval/lessonHelpers';
import { retrieveScoped, buildContextBlock } from './skills/scopedBrainRetriever';
@@ -835,6 +835,16 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.workspace.onDidChangeConfiguration((e) => {
if (e.affectsConfiguration('g1nation')) void settingsPanel.refresh();
}),
+ // Drop the in-memory brain token index whenever the brain profiles or the
+ // active brain change — a profile edit can repoint `localBrainPath`, so a
+ // stale index keyed by the old path must not linger. The persisted on-disk
+ // index is untouched and reloads lazily on the next query.
+ vscode.workspace.onDidChangeConfiguration((e) => {
+ if (e.affectsConfiguration('g1nation.brainProfiles')
+ || e.affectsConfiguration('g1nation.activeBrainId')) {
+ clearBrainTokenIndex();
+ }
+ }),
// Same for SecretStorage updates (token saved/cleared from elsewhere).
context.secrets.onDidChange((e) => {
if (e.key === TELEGRAM_TOKEN_SECRET_KEY) void settingsPanel.refresh();
@@ -915,6 +925,10 @@ export async function activate(context: vscode.ExtensionContext) {
export async function deactivate() {
HealthCheckMonitor.dispose();
+ // Release the in-memory brain token index (and any pending debounced disk
+ // write timer) — the `_states` Map is otherwise never cleared for the
+ // process lifetime.
+ clearBrainTokenIndex();
if (_telegramBot) {
try { await _telegramBot.stop(); } catch (e) { logError('Telegram bot stop during deactivate failed.', e); }
_telegramBot = undefined;
diff --git a/src/features/astraOffice/view/runtime.ts b/src/features/astraOffice/view/runtime.ts
index 3927572..98b2585 100644
--- a/src/features/astraOffice/view/runtime.ts
+++ b/src/features/astraOffice/view/runtime.ts
@@ -408,8 +408,31 @@ function move(role,x,y){
ch.style.left=x+'px';
ch.style.top=y+'px';
}
-setInterval(()=>{Object.keys(chars).forEach(k=>{const a=anim[k];if(a.mode==='walk'){a.frame=(a.frame+1)%5;setSprite(k,'walk',a.frame,a.dir)}else if(a.mode==='work'){a.frame=(a.frame+1)%4;setSprite(k,'work',a.frame)} });},286)
-setInterval(()=>{Object.keys(chars).forEach(k=>{const a=anim[k];if(a.mode==='sit'){a.frame=(a.frame+1)%2;setSprite(k,'sit',a.frame)} });},700)
+// ── Managed intervals (pause while the office view is hidden) ──
+// The pixel-office runs several animation/roam/banter intervals. While the
+// webview tab is not visible they do invisible work and keep timers hot —
+// wasteful. _managedInterval registers each one; a visibilitychange handler
+// pauses them all when the document is hidden and resumes them when shown.
+// Behavior while visible is unchanged (same callbacks, same periods).
+const _managedIntervals=[];
+function _managedInterval(fn,ms){
+ const rec={fn:fn,ms:ms,id:null};
+ rec.id=setInterval(fn,ms);
+ _managedIntervals.push(rec);
+ return rec;
+}
+function _pauseManagedIntervals(){
+ for(const rec of _managedIntervals){ if(rec.id!==null){ clearInterval(rec.id); rec.id=null; } }
+}
+function _resumeManagedIntervals(){
+ for(const rec of _managedIntervals){ if(rec.id===null){ rec.id=setInterval(rec.fn,rec.ms); } }
+}
+document.addEventListener('visibilitychange',()=>{
+ if(document.hidden) _pauseManagedIntervals();
+ else _resumeManagedIntervals();
+});
+_managedInterval(()=>{Object.keys(chars).forEach(k=>{const a=anim[k];if(a.mode==='walk'){a.frame=(a.frame+1)%5;setSprite(k,'walk',a.frame,a.dir)}else if(a.mode==='work'){a.frame=(a.frame+1)%4;setSprite(k,'work',a.frame)} });},286)
+_managedInterval(()=>{Object.keys(chars).forEach(k=>{const a=anim[k];if(a.mode==='sit'){a.frame=(a.frame+1)%2;setSprite(k,'sit',a.frame)} });},700)
// ── 책상 회피 path planner ──
// walkPath의 각 leg를 직선이 아닌 *책상을 우회하는* L자 또는 corridor 경로로
// 펴서 캐릭터가 책상을 가로지르지 않게. 책상이 회전됐을 때를 대비해 padding
@@ -498,7 +521,7 @@ function sendHome(role,mode='sit'){
if(Math.abs(cx-hx)<1&&Math.abs(cy-hy)<1){setSprite(role,mode);return;}
walkPath(role,[st.dock,[hx,hy]],()=>setSprite(role,mode));
}
-setInterval(()=>{
+_managedInterval(()=>{
if(!['idle','done'].includes(_prevStatus || 'idle')) return;
const free=Object.keys(chars).filter(k=>anim[k]?.mode==='sit'&&!chars[k].classList.contains('active'));
if(!free.length)return;
@@ -725,7 +748,7 @@ function _innerThoughtTick(){
const text = _innerThoughtFor(st.agentKey, anim[role].mode);
if(text) _bubbleFromLog(role, text);
}
-setInterval(_innerThoughtTick, 7500);
+_managedInterval(_innerThoughtTick, 7500);
// ── Webtoon-style 티키타카 banter (refactor: pipeline-aware) ──
// 각 phase 에 *시퀀스화된 대화 script* 가 있어 phase 진입 시 한 줄씩 시간 차로 emit.
diff --git a/src/features/secondBrainTrace.ts b/src/features/secondBrainTrace.ts
index 681c196..04fc176 100644
--- a/src/features/secondBrainTrace.ts
+++ b/src/features/secondBrainTrace.ts
@@ -584,7 +584,35 @@ interface FileScan {
documentProject: string | undefined;
}
+/**
+ * mtime-keyed scan cache. The previous implementation re-read (and re-classified)
+ * every brain file from disk on every chat message. We now reuse a parsed
+ * `FileScan` while the file's mtime is unchanged — re-reading only when the file
+ * actually changes. This mirrors the mtime-keyed caching style of
+ * `retrieval/brainIndex.ts` (whose `getBrainTokenIndex` caches tokens the same
+ * way) while keeping the scan output byte-identical, so scoring is unaffected.
+ */
+interface ScanCacheEntry {
+ mtimeMs: number;
+ size: number;
+ scan: FileScan;
+}
+const _scanCache = new Map();
+
function scanFile(file: string, brainRoot: string): FileScan {
+ let mtimeMs = 0;
+ let size = 0;
+ try {
+ const stat = fs.statSync(file);
+ mtimeMs = stat.mtimeMs;
+ size = stat.size;
+ const cached = _scanCache.get(file);
+ if (cached && cached.mtimeMs === mtimeMs && cached.size === size) {
+ return cached.scan;
+ }
+ } catch {
+ // stat failed — fall through and attempt a fresh read (which will also fail safely)
+ }
const relative = path.relative(brainRoot, file);
const title = path.basename(file, path.extname(file));
let content = '';
@@ -598,7 +626,11 @@ function scanFile(file: string, brainRoot: string): FileScan {
const lower = content.toLowerCase();
const documentProject = inferDocumentProject(relative, lower);
const titleWithPath = `${relative.replace(/[\\/]/g, ' ')} ${title}`;
- return { file, relative, title, titleWithPath, content, lower, sourceType, knowledgeRole, documentProject };
+ const scan: FileScan = { file, relative, title, titleWithPath, content, lower, sourceType, knowledgeRole, documentProject };
+ if (mtimeMs > 0) {
+ _scanCache.set(file, { mtimeMs, size, scan });
+ }
+ return scan;
}
function scoreScan(scan: FileScan, terms: string[], intent: SecondBrainQueryIntent, targetProject?: string): SecondBrainTraceDocument {
diff --git a/src/memory/EpisodicMemory.ts b/src/memory/EpisodicMemory.ts
index 1e6d8d0..ef42bb6 100644
--- a/src/memory/EpisodicMemory.ts
+++ b/src/memory/EpisodicMemory.ts
@@ -17,6 +17,14 @@ import { EpisodicEntry, MemoryContextResult } from './types';
export class EpisodicMemory {
private episodeDir: string;
private maxEpisodes: number;
+ /**
+ * mtime-keyed cache of the parsed episode list. The previous implementation
+ * re-read and re-parsed every episode JSON from disk on every message. We now
+ * cache the parsed result and re-read only when the episode directory's mtime
+ * changes (a new/removed/rewritten episode bumps the directory mtime). This
+ * mirrors the mtime-keyed caching style of `retrieval/brainIndex.ts`.
+ */
+ private _episodeCache: { dirMtimeMs: number; episodes: EpisodicEntry[] } | null = null;
constructor(brainPath: string, maxEpisodes = 50) {
this.episodeDir = path.join(brainPath, 'memory', 'episodes');
@@ -85,9 +93,19 @@ export class EpisodicMemory {
/**
* 저장된 모든 에피소드를 최신순으로 로드합니다.
+ *
+ * Result is cached and re-read only when the episode directory's mtime
+ * changes — creating, deleting, or rewriting an episode file all bump the
+ * directory mtime, so the cache stays correct without per-message disk reads.
*/
public loadAllEpisodes(): EpisodicEntry[] {
try {
+ const dirMtimeMs = fs.statSync(this.episodeDir).mtimeMs;
+ const cached = this._episodeCache;
+ if (cached && cached.dirMtimeMs === dirMtimeMs) {
+ return cached.episodes.slice();
+ }
+
const files = fs.readdirSync(this.episodeDir)
.filter((f) => f.endsWith('.json'))
.sort()
@@ -101,7 +119,8 @@ export class EpisodicMemory {
} catch { /* skip corrupted */ }
}
- return episodes;
+ this._episodeCache = { dirMtimeMs, episodes };
+ return episodes.slice();
} catch {
return [];
}
diff --git a/src/memory/LongTermMemory.ts b/src/memory/LongTermMemory.ts
index 1a7b6cc..95a6592 100644
--- a/src/memory/LongTermMemory.ts
+++ b/src/memory/LongTermMemory.ts
@@ -17,13 +17,16 @@ export class LongTermMemory {
private store: LongTermStore;
private filePath: string;
private dirty = false;
+ /** Hard cap on retained entries — oldest are trimmed when exceeded. Default 100 (matches MemoryConfig.longTermMaxEntries). */
+ private maxEntries: number;
- constructor(brainPath: string) {
+ constructor(brainPath: string, maxEntries = 100) {
const memoryDir = path.join(brainPath, 'memory');
if (!fs.existsSync(memoryDir)) {
fs.mkdirSync(memoryDir, { recursive: true });
}
this.filePath = path.join(memoryDir, 'long_term.json');
+ this.maxEntries = maxEntries > 0 ? maxEntries : 100;
this.store = this.load();
}
@@ -62,6 +65,12 @@ export class LongTermMemory {
referenceCount: 0
};
this.store.entries.push(entry);
+ // Enforce the retention cap — drop the oldest entries (by createdAt) once
+ // over the limit. The store array is append-ordered, so the oldest are at
+ // the front; we trim from there.
+ if (this.store.entries.length > this.maxEntries) {
+ this.store.entries.splice(0, this.store.entries.length - this.maxEntries);
+ }
this.dirty = true;
this.save();
return entry;
diff --git a/src/memory/index.ts b/src/memory/index.ts
index ddd6504..3f0bc32 100644
--- a/src/memory/index.ts
+++ b/src/memory/index.ts
@@ -54,7 +54,7 @@ export class MemoryManager {
};
this.shortTerm = new ShortTermMemory();
- this.longTerm = new LongTermMemory(brainPath);
+ this.longTerm = new LongTermMemory(brainPath, this.config.longTermMaxEntries);
this.procedural = new ProceduralMemory(brainPath);
this.episodic = new EpisodicMemory(brainPath, this.config.episodicMaxEpisodes);
this.extractor = new MemoryExtractor();
diff --git a/src/retrieval/scoring.ts b/src/retrieval/scoring.ts
index 944e557..2c82ac4 100644
--- a/src/retrieval/scoring.ts
+++ b/src/retrieval/scoring.ts
@@ -129,11 +129,24 @@ export function expandQuery(tokens: string[]): string[] {
/**
* TF (Term Frequency): 문서 내 용어 빈도
+ *
+ * Takes a precomputed term-count `Map` (built once per document by
+ * `buildTermCounts`) instead of re-scanning the token array per term — the
+ * value is numerically identical to `count / documentTokens.length`.
*/
-function termFrequency(term: string, documentTokens: string[]): number {
- if (documentTokens.length === 0) return 0;
- const count = documentTokens.filter((t) => t === term).length;
- return count / documentTokens.length;
+function termFrequency(term: string, termCounts: Map, totalTokens: number): number {
+ if (totalTokens === 0) return 0;
+ const count = termCounts.get(term) || 0;
+ return count / totalTokens;
+}
+
+/** Build a term -> occurrence-count map for one document's token array (computed once, reused per query term). */
+function buildTermCounts(documentTokens: string[]): Map {
+ const counts = new Map();
+ for (const t of documentTokens) {
+ counts.set(t, (counts.get(t) || 0) + 1);
+ }
+ return counts;
}
/**
@@ -231,7 +244,11 @@ export function scoreTfIdfPreTokenized(
if (documents.length === 0 || queryTokens.length === 0) return [];
const docTokenArrays = documents.map((doc) => doc.tokens);
- const docTokenSets = docTokenArrays.map((tokens) => new Set(tokens));
+ // Precompute, once per document: a term -> count map (used for TF) and the
+ // derived token Set (used for IDF). Both were previously recomputed inside
+ // nested loops — building them once and reusing them is numerically identical.
+ const docTermCounts = docTokenArrays.map((tokens) => buildTermCounts(tokens));
+ const docTokenSets = docTermCounts.map((counts) => new Set(counts.keys()));
// Expand query with synonyms
const expandedQuery = expandQuery(queryTokens);
@@ -248,6 +265,7 @@ export function scoreTfIdfPreTokenized(
return documents.map((doc, index) => {
const docTokens = docTokenArrays[index];
+ const termCounts = docTermCounts[index];
const titleTokens = new Set(doc.titleTokens);
let score = 0;
const matchedTerms: string[] = [];
@@ -262,7 +280,7 @@ export function scoreTfIdfPreTokenized(
else if (conflictCount >= SCORING_CONFIG.CONFLICT_THRESHOLDS.LOW) conflictSeverity = 'LOW';
for (const term of expandedQuery) {
- const tf = termFrequency(term, docTokens);
+ const tf = termFrequency(term, termCounts, docTokens.length);
const idf = idfCache.get(term) || 1;
const tfidf = tf * idf;
diff --git a/src/security.ts b/src/security.ts
index ffff5d9..4a3875e 100644
--- a/src/security.ts
+++ b/src/security.ts
@@ -22,6 +22,15 @@ function getTrustedRoots(workspaceRoot: string): string[] {
roots.push(path.normalize(f.uri.fsPath).toLowerCase());
}
}
+ // Also trust the immediate parent of each root, so sibling projects under a
+ // shared parent (e.g. E:\Wiki\connectai + E:\Wiki\Datacollect) are reachable
+ // for read/list. Guard: never widen to a drive/filesystem root.
+ for (const r of [...roots]) {
+ const parent = path.normalize(path.dirname(r)).toLowerCase();
+ if (parent && parent !== r && path.dirname(parent) !== parent) {
+ roots.push(parent);
+ }
+ }
_trustedRoots = [...new Set(roots)];
return _trustedRoots;
}
@@ -48,6 +57,59 @@ export function validatePath(workspaceRoot: string, targetPath: string): string
return absolutePath;
}
+/**
+ * Splits a command on top-level `&&`, ignoring `&&` that appears inside single-
+ * or double-quoted strings (e.g. a commit message). Returns trimmed, non-empty parts.
+ */
+function splitTopLevelAnd(command: string): string[] {
+ const parts: string[] = [];
+ let buf = '';
+ let quote: string | null = null;
+ for (let i = 0; i < command.length; i++) {
+ const c = command[i];
+ if (quote) {
+ buf += c;
+ if (c === quote) { quote = null; }
+ continue;
+ }
+ if (c === "'" || c === '"') { quote = c; buf += c; continue; }
+ if (c === '&' && command[i + 1] === '&') {
+ parts.push(buf);
+ buf = '';
+ i++; // skip the second '&'
+ continue;
+ }
+ buf += c;
+ }
+ parts.push(buf);
+ return parts.map(p => p.trim()).filter(p => p.length > 0);
+}
+
+/**
+ * Windows PowerShell 5.1 — the default VS Code integrated terminal on Windows —
+ * does not support the `&&` chaining operator (it is a hard parser error, so the
+ * WHOLE command fails to run). Local models emit `&&` constantly because every
+ * git/npm tutorial uses it, and a system-prompt rule alone does not reliably
+ * stop a small model. So rewrite `A && B && C` into a PowerShell-native
+ * conditional chain that preserves short-circuit semantics:
+ *
+ * A && B && C -> A; if ($?) { B; if ($?) { C } }
+ *
+ * `$?` reflects the success of the previous command, so a failed step still
+ * short-circuits the rest — important so e.g. a failed `cd` never lets `git`
+ * run in the wrong directory.
+ */
+function rewriteForPowerShell(command: string): string {
+ if (!command.includes('&&')) { return command; }
+ const parts = splitTopLevelAnd(command);
+ if (parts.length <= 1) { return command; }
+ let chain = parts[parts.length - 1];
+ for (let i = parts.length - 2; i >= 0; i--) {
+ chain = `${parts[i]}; if ($?) { ${chain} }`;
+ }
+ return chain;
+}
+
/**
* Sanitizes terminal commands to prevent destructive actions.
* Uses a combination of blocklist for dangerous patterns and recommendation for allowed tools.
@@ -86,5 +148,7 @@ export function sanitizeCommand(command: string): string {
console.warn(`[Security] Warning: Running uncommon command '${baseCmd}'. Ensure this is intended.`);
}
- return trimmedCmd;
+ // Rewrite `&&` chains for PowerShell (the Windows default terminal) so the
+ // command actually runs instead of failing with a parser error.
+ return rewriteForPowerShell(trimmedCmd);
}
diff --git a/src/sidebarProvider.ts b/src/sidebarProvider.ts
index 5808151..2734bac 100644
--- a/src/sidebarProvider.ts
+++ b/src/sidebarProvider.ts
@@ -25,6 +25,7 @@ import { handleBrainMessage } from './sidebar/brainHandlers';
import { handleChronicleMessage } from './sidebar/chronicleHandlers';
import { handleAgentMessage } from './sidebar/agentHandlers';
import { getOrCreateAgentEntry, resolveScopeForAgent } from './skills/agentKnowledgeMap';
+import { clearBrainTokenIndex } from './retrieval/brainIndex';
import { estimateModelParamsB } from './lib/contextManager';
import { loadExternalSkills, formatSkillsAsPromptBlock } from './skills/externalSkillLoader';
import {
@@ -836,9 +837,15 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
localResourceRoots: [this._extensionUri]
};
+ // Webview event listeners must be disposed — otherwise each re-init of the
+ // view leaks a listener (and its captured `this`). We collect every
+ // listener disposable here, dispose them when the view itself is disposed,
+ // and also register them with the extension subscriptions as a backstop.
+ const viewDisposables: vscode.Disposable[] = [];
+
// [State Persistence Fix] 사이드바가 다시 보여질 때 세팅값 자동 복원
let _lastVisibilityRefresh = 0;
- webviewView.onDidChangeVisibility(() => {
+ viewDisposables.push(webviewView.onDidChangeVisibility(() => {
if (!webviewView.visible) return;
const now = Date.now();
// 5초 이내에 이미 갱신했으면 건너뜀
@@ -850,7 +857,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
void this._sendBrainProfiles();
void this._sendAgentsList();
void this._sendReadyStatus();
- });
+ }));
webviewView.webview.html = this._getHtml(webviewView.webview);
this._agent.setWebview(webviewView.webview);
@@ -858,7 +865,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
void this._restoreActiveSessionIntoView();
void this._sendReadyStatus();
- webviewView.webview.onDidReceiveMessage(async (data) => {
+ viewDisposables.push(webviewView.webview.onDidReceiveMessage(async (data) => {
// dispatch root 진입 trace — "/benchmark 입력했는데 아무 응답 없음" 같은
// 보고가 들어왔을 때 webview message가 정말 도착했는지부터 즉시 판별.
const valuePreview = typeof data?.value === 'string'
@@ -870,7 +877,14 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
if (await handleChronicleMessage(this, data)) return;
if (await handleAgentMessage(this, data)) return;
logInfo(`Unhandled sidebar message: ${data?.type}`);
+ }));
+
+ webviewView.onDidDispose(() => {
+ for (const d of viewDisposables.splice(0)) {
+ try { d.dispose(); } catch { /* already disposed */ }
+ }
});
+ this._context.subscriptions.push(...viewDisposables);
}
_currentSessionId: string | null = null;
@@ -1260,6 +1274,11 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
await vscode.workspace.getConfiguration('g1nation').update('activeBrainId', nextProfile.id, vscode.ConfigurationTarget.Global);
this._currentSessionBrainId = nextProfile.id;
+ // Drop the in-memory brain token index — the active brain (and its path)
+ // may now differ, and the index's `_states` Map is otherwise never cleared.
+ // The persisted on-disk index is left intact and reloads lazily on the
+ // next query for whichever brain is now active.
+ clearBrainTokenIndex();
await this._sendBrainProfiles();
await this._sendBrainStatus();
diff --git a/src/skills/scopedBrainRetriever.ts b/src/skills/scopedBrainRetriever.ts
index 5217136..d90877b 100644
--- a/src/skills/scopedBrainRetriever.ts
+++ b/src/skills/scopedBrainRetriever.ts
@@ -2,7 +2,8 @@ import * as fs from 'fs';
import * as path from 'path';
import { findBrainFiles, summarizeText } from '../utils';
import { isInside } from '../lib/paths';
-import { tokenize, expandQuery, scoreTfIdf, extractBestExcerpt } from '../retrieval/scoring';
+import { tokenize, expandQuery, scoreTfIdfPreTokenized, extractBestExcerpt } from '../retrieval/scoring';
+import { getBrainTokenIndex } from '../retrieval/brainIndex';
import { estimateTokens } from '../retrieval/contextBudget';
/**
@@ -91,33 +92,35 @@ export function retrieveScoped(
});
if (candidates.length === 0) return { ...empty, candidateCount: 0 };
- const documents = candidates.map((file) => {
- let content = '';
- let lastModified = 0;
- try {
- content = fs.readFileSync(file, 'utf8');
- lastModified = fs.statSync(file).mtimeMs;
- } catch { /* skip unreadable file */ }
- return {
- title: path.basename(file, '.md'),
- content,
- lastModified,
- filePath: file,
- relativePath: path.relative(brainRoot, file),
- };
- });
+ // Tokenized docs from the persistent mtime-keyed brain index — unchanged files
+ // are not re-read or re-tokenized. The index tokenizes `${basename} ${content}`
+ // (titleTokens = tokenize(basename)), which is exactly what the previous
+ // `scoreTfIdf` call computed here, so scoring stays byte-identical.
+ const indexed = getBrainTokenIndex(brainRoot, candidates);
+ if (indexed.length === 0) return { ...empty, candidateCount: candidates.length };
const queryTokens = tokenize(query);
const expanded = expandQuery(queryTokens);
- const scored = scoreTfIdf(expanded, documents);
+ const scored = scoreTfIdfPreTokenized(
+ expanded,
+ indexed.map((d) => ({
+ tokens: d.tokens,
+ titleTokens: d.titleTokens,
+ lastModified: d.mtimeMs,
+ conflictCount: d.conflictCount,
+ }))
+ );
const chunks = scored
.filter((s) => s.score > 0)
.sort((a, b) => b.score - a.score)
.slice(0, maxResults)
.map((s) => {
- const doc = documents[s.index];
- const excerpt = extractBestExcerpt(doc.content, expanded, excerptLength);
+ const doc = indexed[s.index];
+ // Only the chosen top-`maxResults` files are read off disk (for excerpt extraction).
+ let content = '';
+ try { content = fs.readFileSync(doc.filePath, 'utf8'); } catch { /* deleted just now — empty excerpt */ }
+ const excerpt = extractBestExcerpt(content, expanded, excerptLength);
const summary = summarizeText(excerpt, excerptLength);
return {
relativePath: doc.relativePath,
diff --git a/src/utils.ts b/src/utils.ts
index a420517..bae6060 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -150,21 +150,50 @@ export function invalidateBrainFilesCache(dir?: string): void {
}
function _walkBrainFiles(dir: string): string[] {
- let results: string[] = [];
- if (!fs.existsSync(dir)) return results;
- const list = fs.readdirSync(dir);
- list.forEach((file) => {
- const filePath = path.join(dir, file);
- const stat = fs.statSync(filePath);
- if (stat && stat.isDirectory()) {
- if (!EXCLUDED_DIRS.has(file)) {
- results = results.concat(_walkBrainFiles(filePath));
+ const results: string[] = [];
+ _walkBrainFilesInto(dir, results);
+ return results;
+}
+
+/**
+ * Recursive walk that pushes `.md` paths into a single shared accumulator.
+ *
+ * Uses `readdirSync(dir, { withFileTypes: true })` so each entry's type comes
+ * from the directory read itself — no extra `fs.statSync` per entry — and pushes
+ * into one array instead of allocating a new array per directory via `.concat`.
+ */
+function _walkBrainFilesInto(dir: string, results: string[]): void {
+ let entries: fs.Dirent[];
+ try {
+ entries = fs.readdirSync(dir, { withFileTypes: true });
+ } catch {
+ // Missing/unreadable directory — matches the previous existsSync guard's behavior.
+ return;
+ }
+ for (const entry of entries) {
+ const name = entry.name;
+ const filePath = path.join(dir, name);
+ let isDir = entry.isDirectory();
+ let isFile = entry.isFile();
+ // Symlinks: Dirent type flags don't follow links, but the previous
+ // statSync-based walk did — resolve them so behavior is unchanged.
+ if (entry.isSymbolicLink()) {
+ try {
+ const stat = fs.statSync(filePath);
+ isDir = stat.isDirectory();
+ isFile = stat.isFile();
+ } catch {
+ continue; // dangling symlink — skip (statSync would have thrown before)
}
- } else if (file.endsWith('.md')) {
+ }
+ if (isDir) {
+ if (!EXCLUDED_DIRS.has(name)) {
+ _walkBrainFilesInto(filePath, results);
+ }
+ } else if (isFile && name.endsWith('.md')) {
results.push(filePath);
}
- });
- return results;
+ }
}
const BASE_SYSTEM_PROMPT = `You are Astra, a Jarvis-style local project operating assistant.
@@ -184,31 +213,53 @@ If the provided initial scan preview is not enough, DO NOT complain that you can
Never say "upload the source code", "provide the files", "파일 내용을 보여주세요", or "먼저 분석할까요?" before attempting access.
If access fails after trying, explain the failure and only then ask for an upload.
+[EXECUTION RULE]
+When the user asks to run, start, launch, boot, or serve something (실행/구동/시작/켜줘/띄워줘/돌려줘/run/start/launch/serve), ACT — never advise.
+- FORBIDDEN: writing a how-to, a numbered tutorial, "먼저 ~를 확인해야 합니다", "~하시기 바랍니다", or telling the user to run a command themselves. The user asked YOU to run it.
+- NEVER invent a script name, port number, or environment variable. If you have not seen it in a file THIS session, do not state it as fact.
+- If you do not know the exact start command, FIRST read the project's package.json with , then emit with the real script name.
+- runs in a real terminal. If the target folder differs from the workspace, cd into its absolute path first.
+- The terminal is Windows PowerShell. Chain steps with ";" — NEVER "&&" (it is a syntax error in PowerShell 5.1). Example: cd 'C:\proj'; git add .; git commit -m 'msg'; git push
+- After acting, reply with ONE short line: what you started and where. No tutorial, no follow-up checklist.
+
+Worked example — user says: "E:\Wiki\Datacollect 서버 실행해줘"
+Step 1 (only when the start script is unknown):
+
+Step 2 (after the real scripts are known — pick the actual one, never a guessed name):
+cd 'E:\Wiki\Datacollect'; npm run start-full
+Then reply: "Datacollect 서버를 start-full 스크립트로 터미널에서 실행했습니다."
+
[STRICT GLOBAL RULES]
1. [NO EMOJIS - ABSOLUTE RULE] NEVER use ANY emojis, emoticons, Unicode pictorial symbols (including but not limited to emoji, kaomoji, Unicode icons), or decorative symbols anywhere in your response. NO EXCEPTIONS. Use plain text dashes (-) or asterisks (*) for bullets. Use plain markdown ## for headers. This rule overrides ALL other formatting instructions.
-2. [UNIQUE HEADINGS] Every markdown heading must be unique and appear exactly once.
+2. [HEADINGS] Every markdown heading must be unique, appear exactly once, and start with exactly one "## " — never "## ##", never "### ###". One space after the hashes.
3. [NO INTERNAL LOGS] Never output , "2nd Brain Trace", or "Debug JSON" blocks.
4. [NO SECTION LEAKAGE] Never output sections named "요청 요약", "사용자 의도 추론", "프로젝트 기록 대상 확인", "핵심 확인 질문", or "근거 파일 경로".
[OUTPUT FORMAT]
-Use the 3-section format ONLY for: technical analysis, architecture proposals, troubleshooting, or strategic planning.
-For conversational replies, quick facts, or simple updates — answer directly without any headers.
+LENGTH decides structure — not topic. Count how long your answer will be:
- ## 요약
- Core conclusion in 2-3 sentences.
+- If the answer is longer than ~4 sentences (analysis, advice, planning, troubleshooting, or any multi-part answer), you MUST lead with a summary block, then the detail:
+
+ ## 핵심 요약
+ - 2 to 4 bullet points. Each bullet is one scannable, self-contained takeaway that captures the WHOLE answer — a reader who stops here still gets the gist.
+ - This block is ALWAYS the very first thing in the response. NEVER place a summary at the bottom. NEVER write an intro paragraph before it — the summary block IS the opening.
## 상세 설명
- - Root cause of the problem.
- - Concrete step-by-step instructions: what to change, which files to edit, which commands to run.
+ Free-form depth. You MAY use your own sub-headers here (e.g. "### 1. ...", "### 2. ..."). This is where the full reasoning and steps go.
## 제안 ← Optional. Only include if a meaningfully better alternative exists. Omit otherwise.
+- If the answer is ~4 sentences or fewer (quick fact, simple update, casual or emotional reply) — answer directly, no headers, no summary block.
+
+The summary block is named exactly "## 핵심 요약" and goes at the TOP. A section literally named "요약" placed at the end is a bug — never do that.
+
[FOLLOW-UP QUESTION RULES]
A follow-up question is a precision tool, not a ritual.
Ask ONE focused question at the very end of the response ONLY if:
- The user's intent is genuinely ambiguous with multiple valid paths, OR
- A critical missing detail would make the current answer completely wrong.
If neither condition is met, give a definitive answer and stop.
+When you do ask: it is ONE plain sentence on its own line. NEVER put it under a heading, NEVER label the section ("핵심 확인 질문", "확인 질문" etc.), NEVER attach a "질문 의도" explanation, NEVER ask two or more questions.
[ENGINEERING STANCE]
- Be a direct engineering partner. Technical precision over polite filler.