diff --git a/.astra-office-preview.html b/.astra-office-preview.html
new file mode 100644
index 0000000..ff22698
--- /dev/null
+++ b/.astra-office-preview.html
@@ -0,0 +1,1793 @@
+
+
+
+
+
+
+
+
+
+
+
+
ASTRA OFFICE
+
Operations Floor
+
+
+
+
+
+
+
+
+ 드래그로 이동 · R 회전 · ]/[ 레이어 · 4px snap
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Current Mission
+
새 요청을 기다리고 있습니다.
+
+
+ 현재 단계
+ 대기 중
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.astra/project-context/architecture.md b/.astra/project-context/architecture.md
index eb11b3a..9aceb6d 100644
--- a/.astra/project-context/architecture.md
+++ b/.astra/project-context/architecture.md
@@ -3,15 +3,15 @@
## Snapshot
-- **Workspace**: `ConnectAI` `v2.2.14` _(absolute path varies by environment; resolved from the active VS Code workspace)_
+- **Workspace**: `ConnectAI` `v2.2.15` _(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**: 248 source files, ~50,110 lines across 5 top-level modules.
+- **Stats**: 250 source files, ~50,558 lines across 5 top-level modules.
## Last Refresh
-- **Time**: 2026-05-16T13:04:11.625Z
-- **Files newly analysed**: 6
-- **Files reused from cache**: 242
+- **Time**: 2026-05-16T13:16:41.338Z
+- **Files newly analysed**: 3
+- **Files reused from cache**: 247
## Directory Map
```mermaid
@@ -41,7 +41,7 @@ flowchart LR
media["media/
6 files"]
tests["tests/
33 files"]
core_py["core_py/
6 files"]
- docs["docs/
76 files"]
+ docs["docs/
78 files"]
tests --> src
```
@@ -64,7 +64,7 @@ flowchart LR
## Modules
-### `src/` — 127 files, ~33,943 lines
+### `src/` — 127 files, ~34,341 lines
**Sub-directories**
- `src/features/` (54) — Astra Office — public API. 다음 세션에서 추가될 OfficeSnapshot presenter / schema 도 같은 entry 로 노출 예정. 현재 노출: full webview panel H
@@ -97,7 +97,7 @@ flowchart LR
- `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/features/approval/approvalQueue.ts` (129 lines)
- `src/integrations/telegram/telegramClient.ts` (154 lines)
-- `src/features/astraOffice/view/runtime.ts` (1254 lines) — 자동 분리: src/sidebarProvider.ts 4002-5116 (IIFE 본문) 에서 추출. 동작 동등. ${assets.derivedBase} placeholder 는 panelHtml 에서 .replace() 로 실제 값 주입. 다음 세션에서 OfficeSnapshot 기반으로 단계적으로 잘라낼 예정.
+- `src/features/astraOffice/view/runtime.ts` (1350 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
@@ -160,10 +160,10 @@ flowchart LR
- `core_py/optimizer.py` (55 lines)
- `core_py/queue_worker.py` (82 lines)
-### `docs/` — 76 files, ~3,084 lines
+### `docs/` — 78 files, ~3,134 lines
**Sub-directories**
-- `docs/records/` (63) — Astra Project Chronicle Records
+- `docs/records/` (65) — Astra Project Chronicle Records
- `docs/docs/` (5) — docs Chronicle Records
**Key files**
@@ -173,7 +173,7 @@ 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` (140 lines) — Project Timeline
+- `docs/records/ConnectAI/timeline.md` (146 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
@@ -224,7 +224,7 @@ flowchart LR
- `g1nation.calendar.connect` — Astra: Google Calendar (iCal) 연결 📅
- `g1nation.calendar.refresh` — Astra: Google Calendar 새로고침 📅
- `g1nation.calendar.connectOAuth` — Astra: Google Calendar OAuth 연결 (쓰기) 🔐
-- **Configuration** (50 settings):
+- **Configuration** (56 settings):
- `g1nation.multiAgentEnabled` *(boolean)* _(default: `false`)_ — Enable Multi-Agent Workflow (Planner -> Researcher -> Writer) for complex tasks.
- `g1nation.memoryEnabled` *(boolean)* _(default: `true`)_ — Enable layered memory injection before each model response.
- `g1nation.memoryShortTermMessages` *(number)* _(default: `8`)_ — Number of recent conversation messages included as short-term memory.
@@ -275,6 +275,12 @@ flowchart LR
- `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
- `g1nation.company.pixelOffice.bubbles` *(boolean)* _(default: `true`)_ — Show short comic-style speech bubbles above the Pixel Office character on status changes / key events (e.g. '코드 들어간다', '잠깐, 이건 다시 보자', '좋아, 끝났다!'). Bubbles are purely narrative — they never influence
+ - `g1nation.google.clientId` *(string)* _(default: `""`)_
+ - `g1nation.google.clientSecret` *(string)* _(default: `""`)_
+ - `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주치.
## Dependencies
- **Runtime** (2): `@lmstudio/sdk`, `pdf-parse`
@@ -322,7 +328,7 @@ Astra는 대표님의 명시적인 승인 하에 로컬 시스템의 강력한
**Designed for High-Performance Decision Making.**
Copyright (C) **g1nation**. All rights reserved.
-_Last auto-scan: 2026-05-16T13:04:11.625Z · signature `b9442404`_
+_Last auto-scan: 2026-05-16T13:16:41.338Z · signature `325106ed`_
## Purpose
diff --git a/.astra/project-context/scan-cache.json b/.astra/project-context/scan-cache.json
index e013442..2a10285 100644
--- a/.astra/project-context/scan-cache.json
+++ b/.astra/project-context/scan-cache.json
@@ -1,6 +1,6 @@
{
"version": 1,
- "generatedAt": "2026-05-16T13:04:11.635Z",
+ "generatedAt": "2026-05-16T13:16:41.347Z",
"files": {
"src/agent.ts": {
"mtimeMs": 1778936503000,
@@ -362,21 +362,21 @@
"imports": []
},
"src/features/astraOffice/view/officeBody.ts": {
- "mtimeMs": 1778931340000,
- "size": 1804,
- "lines": 21,
- "role": "자동 분리: src/sidebarProvider.ts 3984-4001 에서 추출. 동작 동등.",
+ "mtimeMs": 1778937173000,
+ "size": 3988,
+ "lines": 102,
+ "role": "",
"imports": []
},
"src/features/astraOffice/view/officeStyles.ts": {
- "mtimeMs": 1778931340000,
- "size": 14309,
- "lines": 121,
- "role": "자동 분리: src/sidebarProvider.ts 3866-3982 에서 추출. 동작 동등. design doc: docs/ASTRAOFFICEREFACTOR.md",
+ "mtimeMs": 1778937307000,
+ "size": 20643,
+ "lines": 342,
+ "role": "",
"imports": []
},
"src/features/astraOffice/view/panelHtml.ts": {
- "mtimeMs": 1778931468000,
+ "mtimeMs": 1778937313000,
"size": 923,
"lines": 26,
"role": "Full Astra Office webview HTML composition. 옛 sidebarProvider.ts 의 거대한 pixelOfficePanelHtml 을 4개 파일로 분리한 entry. 이번 세션은 동작 동등 분리 만. 다음 세션에 mini view 와 공통 presenter 도입.",
@@ -387,9 +387,9 @@
]
},
"src/features/astraOffice/view/runtime.ts": {
- "mtimeMs": 1778933617000,
- "size": 58118,
- "lines": 1254,
+ "mtimeMs": 1778937401000,
+ "size": 62934,
+ "lines": 1350,
"role": "자동 분리: src/sidebarProvider.ts 4002-5116 (IIFE 본문) 에서 추출. 동작 동등. ${assets.derivedBase} placeholder 는 panelHtml 에서 .replace() 로 실제 값 주입. 다음 세션에서 OfficeSnapshot 기반으로 단계적으로 잘라낼 예정.",
"imports": []
},
@@ -1860,7 +1860,7 @@
"imports": []
},
"docs/records/ConnectAI/chronicle.config.json": {
- "mtimeMs": 1778932145000,
+ "mtimeMs": 1778937290000,
"size": 416,
"lines": 11,
"role": "JSON configuration",
@@ -2111,6 +2111,20 @@
"role": "Development Log: REFLECTOR 에이전트가 1인 기업 에이전트 목록에는 안보이는데",
"imports": []
},
+ "docs/records/ConnectAI/development/2026-05-16_astra-google-calendar-oauth-연결_implementation-2.md": {
+ "mtimeMs": 1778937290000,
+ "size": 1230,
+ "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,
+ "lines": 22,
+ "role": "Development Log: Astra: Google Calendar OAuth 연결",
+ "imports": []
+ },
"docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업-할-거야.md": {
"mtimeMs": 1778690673000,
"size": 652,
@@ -2189,9 +2203,9 @@
"imports": []
},
"docs/records/ConnectAI/timeline.md": {
- "mtimeMs": 1778902489000,
- "size": 9082,
- "lines": 140,
+ "mtimeMs": 1778937290000,
+ "size": 9336,
+ "lines": 146,
"role": "Project Timeline",
"imports": []
},
diff --git a/.astra/tests/stress/.astra/cache/259a37934ead3910a8722b82054d46d2ca2057b05c488be1dcf439166ac5a9a1.json b/.astra/tests/stress/.astra/cache/259a37934ead3910a8722b82054d46d2ca2057b05c488be1dcf439166ac5a9a1.json
index 70d8f2d..c9dbd1e 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": 1778936679275,
+ "createdAt": 1778937508211,
"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 0ad5117..2064d47 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": 1778936679275,
+ "createdAt": 1778937508205,
"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 4f0fa21..a7d0652 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": 1778936679274,
+ "createdAt": 1778937508200,
"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 7126ee7..c9438a1 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_1778936679262\ndate: 2026-05-16T13:04:39.276Z\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]** 핵심 정보 수집 및 분석 중... (0ms)\n- **[WRITER]** 최종 리포트 작성 및 편집 중... (1ms)\n",
- "createdAt": 1778936679276,
+ "result": "---\nid: stress_conflict_1778937508187\ndate: 2026-05-16T13:18:28.211Z\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]** 최종 리포트 작성 및 편집 중... (10ms)\n",
+ "createdAt": 1778937508211,
"modelVersion": "unknown"
}
\ No newline at end of file
diff --git a/.astra/tests/stress/.astra/missions/stress_conflict_1778936679262.json b/.astra/tests/stress/.astra/missions/stress_conflict_1778937508187.json
similarity index 81%
rename from .astra/tests/stress/.astra/missions/stress_conflict_1778936679262.json
rename to .astra/tests/stress/.astra/missions/stress_conflict_1778937508187.json
index 720f644..f5fd0e5 100644
--- a/.astra/tests/stress/.astra/missions/stress_conflict_1778936679262.json
+++ b/.astra/tests/stress/.astra/missions/stress_conflict_1778937508187.json
@@ -1,8 +1,8 @@
{
- "missionId": "stress_conflict_1778936679262",
+ "missionId": "stress_conflict_1778937508187",
"status": "completed",
- "startTime": "2026-05-16T13:04:39.262Z",
- "totalElapsedMs": 14,
+ "startTime": "2026-05-16T13:18:28.187Z",
+ "totalElapsedMs": 25,
"results": {
"planner": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
"researcher": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
@@ -18,28 +18,28 @@
"to": "planner",
"durationMs": 12,
"message": "전략 수립 중...",
- "ts": "2026-05-16T13:04:39.274Z"
+ "ts": "2026-05-16T13:18:28.199Z"
},
{
"from": "planner",
"to": "researcher",
- "durationMs": 0,
+ "durationMs": 1,
"message": "핵심 정보 수집 및 분석 중...",
- "ts": "2026-05-16T13:04:39.274Z"
+ "ts": "2026-05-16T13:18:28.200Z"
},
{
"from": "researcher",
"to": "writer",
- "durationMs": 1,
+ "durationMs": 10,
"message": "최종 리포트 작성 및 편집 중...",
- "ts": "2026-05-16T13:04:39.275Z"
+ "ts": "2026-05-16T13:18:28.210Z"
},
{
"from": "writer",
"to": "completed",
- "durationMs": 1,
+ "durationMs": 2,
"message": "미션 완료",
- "ts": "2026-05-16T13:04:39.276Z"
+ "ts": "2026-05-16T13:18:28.212Z"
}
],
"resilienceMetrics": {
diff --git a/PATCHNOTES.md b/PATCHNOTES.md
index 2cbbbb5..34ec073 100644
--- a/PATCHNOTES.md
+++ b/PATCHNOTES.md
@@ -1,5 +1,18 @@
# Astra Patch Notes
+## v2.2.16 (2026-05-16)
+### 🏢 Astra Office UI Overhaul: Operations Floor Experience
+- **차세대 오피스 UI 도입:** 단순한 뷰어를 넘어 실제 운영 본부(Operations Floor)의 느낌을 주는 대대적인 인터페이스 개편을 단행했습니다.
+- **데이터 기반 사이드 패널:** 에이전트 라인업(Team), 운영 브리프(Signal), 활동 도크(Activity Dock) 등 전문적인 정보 레이아웃을 탑재했습니다.
+- **비주얼 경험 고도화:** 글래스모피즘(Glassmorphism)과 그라데이션 백그라운드, 정교한 상태 배지(Pills)를 통해 더욱 프리미엄한 룩앤필을 구현했습니다.
+- **진행 상황 가시화:** 미션별 진행률, 단계 보고, 주의 신호 감지 등 에이전트의 작업 흐름을 한눈에 파악할 수 있는 대시보드 기능을 강화했습니다.
+- **구글 캘린더 OAuth 연동 기반 마련:** 구글 캘린더와의 정식 연동을 위한 인증 시스템 및 구현 기록을 통합했습니다.
+- **신규 패키징:** `astra-2.2.16.vsix` 패키지를 통해 더욱 강력하고 아름다워진 아스트라 오피스를 배포합니다.
+
+---
+
+
+
## v2.2.15 (2026-05-16)
### 💎 Astra Office Refactor & Multi-Service Integration (Calendar, Sheets, Tasks)
- **아스트라 오피스(Astra Office) 대규모 리팩토링:** 모놀리식 구조에서 기능 기반 모듈 구조(`src/features/astraOffice/`)로 전면 개편했습니다. `OfficeSnapshot` 데이터 모델 도입을 통해 에이전트의 활동 가시성과 레이아웃 관리 능력을 혁신적으로 개선했습니다.
diff --git a/docs/records/ConnectAI/chronicle.config.json b/docs/records/ConnectAI/chronicle.config.json
index 317538a..34b28f5 100644
--- a/docs/records/ConnectAI/chronicle.config.json
+++ b/docs/records/ConnectAI/chronicle.config.json
@@ -7,5 +7,5 @@
"corePurpose": "",
"detailLevel": "standard",
"createdAt": "2026-05-13T13:09:33.788Z",
- "updatedAt": "2026-05-16T11:49:05.841Z"
+ "updatedAt": "2026-05-16T13:14:50.049Z"
}
diff --git a/docs/records/ConnectAI/development/2026-05-16_astra-google-calendar-oauth-연결_implementation-2.md b/docs/records/ConnectAI/development/2026-05-16_astra-google-calendar-oauth-연결_implementation-2.md
new file mode 100644
index 0000000..4ed1284
--- /dev/null
+++ b/docs/records/ConnectAI/development/2026-05-16_astra-google-calendar-oauth-연결_implementation-2.md
@@ -0,0 +1,22 @@
+# Development Log: Astra: Google Calendar OAuth 연결
+
+## Purpose
+Record the implementation or verification outcome from the current conversation.
+
+## Implementation Summary
+네, Google Calendar OAuth 연결이 완료되었다는 점 확인했습니다. 이 정보는 프로젝트의 기능 구현이나 일정 관리 부분에 중요한 전제 조건이 됩니다. 하지만 현재 아키텍처 최신화 작업으로 돌아가서 말씀드리자면, 제가 분석하고 업데이트해야 할 **`ARCHITECTURE_ANALYSIS.md` 문서 자체**의 내용이 필요합니다. 파일 접근 또는 내용 확인이 불가능하여 어떤 부분을 수정해야 하는지 판단할 근거가 없습니다. 문서 내용을 복사해서 붙여주시거나, 해당 파일을 다시 한번 읽을 수 있도록 조치해 주시면, 바로 분석에 착수하겠습니다.
+
+## Architecture
+Captured automatically from the assistant response and active project context.
+
+## Changed Files
+- ARCHITECTURE_ANALYSIS.md
+
+## 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/development/2026-05-16_astra-google-calendar-oauth-연결_implementation.md b/docs/records/ConnectAI/development/2026-05-16_astra-google-calendar-oauth-연결_implementation.md
new file mode 100644
index 0000000..76418ae
--- /dev/null
+++ b/docs/records/ConnectAI/development/2026-05-16_astra-google-calendar-oauth-연결_implementation.md
@@ -0,0 +1,22 @@
+# Development Log: Astra: Google Calendar OAuth 연결
+
+## Purpose
+Record the implementation or verification outcome from the current conversation.
+
+## Implementation Summary
+제가 분석을 수행하려면 먼저 `ARCHITECTURE_ANALYSIS.md` 파일의 실제 내용이 필요합니다. 이전 확인 결과, 해당 파일을 읽는 과정에서 접근에 실패했거나 내용을 확인할 수 없었습니다. 따라서 제가 문서의 최신화 작업을 시작하고 어떤 부분을 업데이트해야 할지 판단하기 위해서는 **해당 파일의 전체 내용을 제공**해 주시거나, 파일이 실제로 접근 가능한 상태인지 다시 확인해 주셔야 합니다. 파일 내용을 제공해 주시면, 그 내용을 바탕으로 현재 프로젝트 상황과 기술적 맥락을 고려하여 최신화 방향과 구체적인 수정 사항을 제시해 드리겠습니다.
+
+## Architecture
+Captured automatically from the assistant response and active project context.
+
+## Changed Files
+- ARCHITECTURE_ANALYSIS.md
+
+## 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 7ec7984..10a5720 100644
--- a/docs/records/ConnectAI/timeline.md
+++ b/docs/records/ConnectAI/timeline.md
@@ -138,3 +138,9 @@
## 2026-05-15
- Auto decision record created: decisions\ADR-0014-astra-office-부분-관련해서-개선할-부분이-너무-많아-개선점이-무었이-있는지-의견-주면-좋겠어.md
+
+## 2026-05-16
+- Auto development record created: development/2026-05-16_astra-google-calendar-oauth-연결_implementation.md
+
+## 2026-05-16
+- Auto development record created: development/2026-05-16_astra-google-calendar-oauth-연결_implementation-2.md
diff --git a/package.json b/package.json
index a0a187b..cc0ffa6 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.15",
+ "version": "2.2.16",
"publisher": "g1nation",
"license": "MIT",
"icon": "assets/icon.png",
@@ -490,6 +490,43 @@
"type": "boolean",
"default": true,
"description": "Show short comic-style speech bubbles above the Pixel Office character on status changes / key events (e.g. '코드 들어간다', '잠깐, 이건 다시 보자', '좋아, 끝났다!'). Bubbles are purely narrative — they never influence the agent's decisions. Disable for a quieter UI."
+ },
+ "g1nation.google.clientId": {
+ "type": "string",
+ "default": "",
+ "scope": "machine",
+ "markdownDescription": "Google OAuth Client ID — `console.cloud.google.com/apis/credentials` → OAuth 2.0 Client ID (Desktop app) 생성 후 복사. **`Astra: Google Calendar OAuth 연결 (쓰기) 🔐`** 명령을 한 번 실행하면 이 값이 자동으로 채워집니다. Calendar + Sheets 둘 다 이 자격증명을 공유.\n\n_scope: machine — Settings Sync 로 다른 기기에 공유되지 않음._"
+ },
+ "g1nation.google.clientSecret": {
+ "type": "string",
+ "default": "",
+ "scope": "machine",
+ "markdownDescription": "Google OAuth Client Secret — Client ID 와 같은 페이지에서 발급. Desktop app OAuth 의 secret 은 Google 가이드상 *진짜 비밀이 아닌 식별자* 지만, settings.json 에 그대로 들어가므로 git 커밋 / 화면 공유 시 주의.\n\n_scope: machine — Settings Sync 안 됨._"
+ },
+ "g1nation.google.calendarId": {
+ "type": "string",
+ "default": "primary",
+ "markdownDescription": "일정을 등록할 Google Calendar 식별자. 기본 `primary` (본인 메인 캘린더). 특정 캘린더 쓰려면 Calendar 설정 → 캘린더 통합 → 'Calendar ID' 복사 (예: `xxxxxxx@group.calendar.google.com`)."
+ },
+ "g1nation.google.defaultEventDurationMinutes": {
+ "type": "number",
+ "default": 60,
+ "minimum": 5,
+ "maximum": 1440,
+ "description": "end / duration 둘 다 없는 일정의 기본 길이 (분). agent 가 회의록에서 시각만 추출하고 종료 시각은 명시 안 했을 때 적용."
+ },
+ "g1nation.google.icalUrl": {
+ "type": "string",
+ "default": "",
+ "scope": "machine",
+ "markdownDescription": "Google Calendar **비공개 iCal URL** — 읽기 전용 모드용. `calendar.google.com/calendar/u/0/r/settings` → 본인 캘린더 → '캘린더 통합' → '비공개 주소(iCal 형식)' 복사. **이 URL 을 가진 사람은 본인 캘린더 모든 일정을 볼 수 있으니 절대 공개 금지.**\n\n_scope: machine — Settings Sync 안 됨. OAuth 와는 별개 — 둘 다 셋업해도 되고 한 쪽만 해도 됨._"
+ },
+ "g1nation.google.icalDaysAhead": {
+ "type": "number",
+ "default": 14,
+ "minimum": 1,
+ "maximum": 90,
+ "description": "iCal 캐시에 포함할 다가오는 일정 기간 (일). default 14 = 2주치."
}
}
}
diff --git a/src/extension.ts b/src/extension.ts
index f0b644a..b172655 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -1049,25 +1049,47 @@ async function runConnectGoogleCalendarOAuth(context: vscode.ExtensionContext) {
}
}
- const clientId = await vscode.window.showInputBox({
- title: 'Google OAuth Client ID',
- prompt: 'Credentials 페이지에서 복사한 Client ID',
- placeHolder: 'xxxxxxxx.apps.googleusercontent.com',
- value: cur.clientId,
- ignoreFocusOut: true,
- validateInput: (v) => (v || '').trim() ? null : '비어있어요',
- });
- if (!clientId) return;
- const clientSecret = await vscode.window.showInputBox({
- title: 'Google OAuth Client Secret',
- prompt: '같은 화면의 Client Secret',
- placeHolder: 'GOCSPX-...',
- value: cur.clientSecret,
- password: true,
- ignoreFocusOut: true,
- validateInput: (v) => (v || '').trim() ? null : '비어있어요',
- });
- if (!clientSecret) return;
+ // Settings 에 이미 채워져 있으면 그대로 쓰겠냐고 물어봄 — 매번 똑같은 값 다시 입력하기 귀찮음.
+ const haveBoth = !!(cur.clientId && cur.clientSecret);
+ let clientId: string | undefined = cur.clientId;
+ let clientSecret: string | undefined = cur.clientSecret;
+ if (haveBoth) {
+ const useExisting = await vscode.window.showInformationMessage(
+ `Settings (g1nation.google) 에 이미 Client ID/Secret 이 있습니다.\nID: ${cur.clientId!.slice(0, 20)}…\n\n이 값으로 OAuth 진행할까요?`,
+ { modal: false },
+ '예 (Settings 값 사용)',
+ '아니오 (새로 입력)',
+ '취소',
+ );
+ if (useExisting === '취소' || !useExisting) return;
+ if (useExisting === '아니오 (새로 입력)') {
+ clientId = undefined;
+ clientSecret = undefined;
+ }
+ }
+ if (!clientId) {
+ clientId = await vscode.window.showInputBox({
+ title: 'Google OAuth Client ID',
+ prompt: 'Credentials 페이지에서 복사한 Client ID — 자동으로 Settings(g1nation.google.clientId)에 저장됨',
+ placeHolder: 'xxxxxxxx.apps.googleusercontent.com',
+ value: cur.clientId,
+ ignoreFocusOut: true,
+ validateInput: (v) => (v || '').trim() ? null : '비어있어요',
+ });
+ if (!clientId) return;
+ }
+ if (!clientSecret) {
+ clientSecret = await vscode.window.showInputBox({
+ title: 'Google OAuth Client Secret',
+ prompt: '같은 화면의 Client Secret — Settings(g1nation.google.clientSecret)에 저장됨',
+ placeHolder: 'GOCSPX-...',
+ value: cur.clientSecret,
+ password: true,
+ ignoreFocusOut: true,
+ validateInput: (v) => (v || '').trim() ? null : '비어있어요',
+ });
+ if (!clientSecret) return;
+ }
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
diff --git a/src/features/astraOffice/view/officeBody.ts b/src/features/astraOffice/view/officeBody.ts
index dc5dfbc..4f07be1 100644
--- a/src/features/astraOffice/view/officeBody.ts
+++ b/src/features/astraOffice/view/officeBody.ts
@@ -1,21 +1,102 @@
-// 자동 분리: src/sidebarProvider.ts 3984-4001 에서 추출. 동작 동등.
export const OFFICE_BODY = `
-
-
-
-