feat(architecture): add multi-subproject awareness and automatic context resync
- Implemented subproject root resolution based on active editor hint - Added debounced event listener for active editor changes to trigger chip status updates - Updated sidebar provider to re-resolve active subproject root on every chip build - This ensures correct architecture context is injected when working in a monorepo or multi-root-style parent folder
This commit is contained in:
@@ -3,15 +3,15 @@
|
|||||||
<!-- ASTRA:AUTO-START -->
|
<!-- ASTRA:AUTO-START -->
|
||||||
|
|
||||||
## Snapshot
|
## Snapshot
|
||||||
- **Workspace**: `ConnectAI` `v2.0.9` _(absolute path varies by environment; resolved from the active VS Code workspace)_
|
- **Workspace**: `ConnectAI` `v2.1.0` _(absolute path varies by environment; resolved from the active VS Code workspace)_
|
||||||
- **Description**: The personal intelligence layer for Antigravity and VS Code. A private cognitive partner for deep project context, memory, and proactive strategic decision-making.
|
- **Description**: The personal intelligence layer for Antigravity and VS Code. A private cognitive partner for deep project context, memory, and proactive strategic decision-making.
|
||||||
- **Stack**: TypeScript, Node.js, VS Code Extension, LM Studio SDK, Test runner
|
- **Stack**: TypeScript, Node.js, VS Code Extension, LM Studio SDK, Test runner
|
||||||
- **Stats**: 201 source files, ~35,737 lines across 5 top-level modules.
|
- **Stats**: 202 source files, ~35,762 lines across 5 top-level modules.
|
||||||
|
|
||||||
## Last Refresh
|
## Last Refresh
|
||||||
- **Time**: 2026-05-13T16:44:14.023Z
|
- **Time**: 2026-05-13T16:54:00.117Z
|
||||||
- **Files newly analysed**: 8
|
- **Files newly analysed**: 5
|
||||||
- **Files reused from cache**: 193
|
- **Files reused from cache**: 197
|
||||||
|
|
||||||
## Directory Map
|
## Directory Map
|
||||||
```mermaid
|
```mermaid
|
||||||
@@ -41,7 +41,7 @@ flowchart LR
|
|||||||
media["media/<br/>6 files"]
|
media["media/<br/>6 files"]
|
||||||
tests["tests/<br/>27 files"]
|
tests["tests/<br/>27 files"]
|
||||||
core_py["core_py/<br/>6 files"]
|
core_py["core_py/<br/>6 files"]
|
||||||
docs["docs/<br/>62 files"]
|
docs["docs/<br/>63 files"]
|
||||||
tests --> src
|
tests --> src
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -117,14 +117,14 @@ flowchart LR
|
|||||||
- `media/settings-panel.html` (164 lines) — Astra Settings
|
- `media/settings-panel.html` (164 lines) — Astra Settings
|
||||||
- `media/settings-panel.js` (270 lines)
|
- `media/settings-panel.js` (270 lines)
|
||||||
|
|
||||||
### `tests/` — 27 files, ~4,932 lines
|
### `tests/` — 27 files, ~4,938 lines
|
||||||
*Depends on*: `src/`
|
*Depends on*: `src/`
|
||||||
|
|
||||||
**Sub-directories**
|
**Sub-directories**
|
||||||
- `tests/mocks/` (1) — 1 files (.js)
|
- `tests/mocks/` (1) — 1 files (.js)
|
||||||
|
|
||||||
**Key files**
|
**Key files**
|
||||||
- `tests/agentEngine.test.ts` (776 lines) — AgentEngine Integration Tests & Performance Benchmarks 검증 대상: 1. ErrorClassifier — 오류 유형(Transient/Permanent/Abort) 자동 분류 2. ErrorRecoveryMatrix — 각 규칙이 의도한 대응 전략으로 매핑되는지 검증 3. resilientExecute — 지수 백
|
- `tests/agentEngine.test.ts` (782 lines) — AgentEngine Integration Tests & Performance Benchmarks 검증 대상: 1. ErrorClassifier — 오류 유형(Transient/Permanent/Abort) 자동 분류 2. ErrorRecoveryMatrix — 각 규칙이 의도한 대응 전략으로 매핑되는지 검증 3. resilientExecute — 지수 백
|
||||||
- `tests/lmStudioLifecycle.test.ts` (318 lines) — Unit tests for ModelLifecycleManager. Strategy: inject mock ILMStudioClient and a simple in-memory IActivityTracker. No real LM Studio or SDK is touched — the manager file does not import the SDK dire
|
- `tests/lmStudioLifecycle.test.ts` (318 lines) — Unit tests for ModelLifecycleManager. Strategy: inject mock ILMStudioClient and a simple in-memory IActivityTracker. No real LM Studio or SDK is touched — the manager file does not import the SDK dire
|
||||||
- `tests/telegramBot.test.ts` (363 lines) — Unit tests for TelegramBot + truncateForTelegram. Strategy: - TelegramBot is driven by an injected ITelegramClient stub. We script getUpdates to return queued batches and assert that: - the offset cur
|
- `tests/telegramBot.test.ts` (363 lines) — Unit tests for TelegramBot + truncateForTelegram. Strategy: - TelegramBot is driven by an injected ITelegramClient stub. We script getUpdates to return queued batches and assert that: - the offset cur
|
||||||
- `tests/lmStudioStreamer.test.ts` (220 lines) — Unit tests for LMStudioStreamer. Strategy: inject a fake ILMStudioClient that returns a fake model handle whose respond() yields a controllable async iterable. No real SDK or WebSocket touched.
|
- `tests/lmStudioStreamer.test.ts` (220 lines) — Unit tests for LMStudioStreamer. Strategy: inject a fake ILMStudioClient that returns a fake model handle whose respond() yields a controllable async iterable. No real SDK or WebSocket touched.
|
||||||
@@ -160,10 +160,10 @@ flowchart LR
|
|||||||
- `core_py/optimizer.py` (55 lines)
|
- `core_py/optimizer.py` (55 lines)
|
||||||
- `core_py/queue_worker.py` (82 lines)
|
- `core_py/queue_worker.py` (82 lines)
|
||||||
|
|
||||||
### `docs/` — 62 files, ~2,586 lines
|
### `docs/` — 63 files, ~2,605 lines
|
||||||
|
|
||||||
**Sub-directories**
|
**Sub-directories**
|
||||||
- `docs/records/` (50) — Astra Project Chronicle Records
|
- `docs/records/` (51) — Astra Project Chronicle Records
|
||||||
- `docs/docs/` (5) — docs Chronicle Records
|
- `docs/docs/` (5) — docs Chronicle Records
|
||||||
|
|
||||||
**Key files**
|
**Key files**
|
||||||
@@ -172,7 +172,7 @@ flowchart LR
|
|||||||
- `docs/EXPERIENCE_MEMORY_PLAN.md` (122 lines) — Experience Memory (Mistake / Lesson Loop) — Implementation Plan
|
- `docs/EXPERIENCE_MEMORY_PLAN.md` (122 lines) — Experience Memory (Mistake / Lesson Loop) — Implementation Plan
|
||||||
- `docs/records/ConnectAI/development/2026-05-02_connectai_project_knowledge_overview.md` (121 lines) — Astra Project Knowledge Overview
|
- `docs/records/ConnectAI/development/2026-05-02_connectai_project_knowledge_overview.md` (121 lines) — Astra Project Knowledge Overview
|
||||||
- `docs/records/ConnectAI/development/2026-05-03_connectai_project_knowledge_overview.md` (121 lines) — Astra Project Knowledge Overview
|
- `docs/records/ConnectAI/development/2026-05-03_connectai_project_knowledge_overview.md` (121 lines) — Astra Project Knowledge Overview
|
||||||
- `docs/records/ConnectAI/timeline.md` (122 lines) — Project Timeline
|
- `docs/records/ConnectAI/timeline.md` (125 lines) — Project Timeline
|
||||||
- `docs/Advanced_Features_Implementation_Guide.md` (40 lines) — Advanced Features Implementation Guide
|
- `docs/Advanced_Features_Implementation_Guide.md` (40 lines) — Advanced Features Implementation Guide
|
||||||
- `docs/PROJECT_CHRONICLE_GUARD_ROADMAP.md` (43 lines) — Project Chronicle Guard: Search Engine Roadmap
|
- `docs/PROJECT_CHRONICLE_GUARD_ROADMAP.md` (43 lines) — Project Chronicle Guard: Search Engine Roadmap
|
||||||
- `docs/UX_UI_Consistency_Guidelines.md` (44 lines) — UX/UI Consistency Guidelines
|
- `docs/UX_UI_Consistency_Guidelines.md` (44 lines) — UX/UI Consistency Guidelines
|
||||||
@@ -307,7 +307,7 @@ Astra는 대표님의 명시적인 승인 하에 로컬 시스템의 강력한
|
|||||||
**Designed for High-Performance Decision Making.**
|
**Designed for High-Performance Decision Making.**
|
||||||
Copyright (C) **g1nation**. All rights reserved.
|
Copyright (C) **g1nation**. All rights reserved.
|
||||||
|
|
||||||
_Last auto-scan: 2026-05-13T16:44:14.023Z · signature `c63276ae`_
|
_Last auto-scan: 2026-05-13T16:54:00.117Z · signature `2c245387`_
|
||||||
<!-- ASTRA:AUTO-END -->
|
<!-- ASTRA:AUTO-END -->
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"generatedAt": "2026-05-13T16:44:14.033Z",
|
"generatedAt": "2026-05-13T16:54:00.128Z",
|
||||||
"files": {
|
"files": {
|
||||||
"src/agent.ts": {
|
"src/agent.ts": {
|
||||||
"mtimeMs": 1778683690000,
|
"mtimeMs": 1778683690000,
|
||||||
@@ -923,8 +923,8 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/sidebarProvider.ts": {
|
"src/sidebarProvider.ts": {
|
||||||
"mtimeMs": 1778686896000,
|
"mtimeMs": 1778690954000,
|
||||||
"size": 127185,
|
"size": 127595,
|
||||||
"lines": 2934,
|
"lines": 2934,
|
||||||
"role": "",
|
"role": "",
|
||||||
"imports": [
|
"imports": [
|
||||||
@@ -1056,9 +1056,9 @@
|
|||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"tests/agentEngine.test.ts": {
|
"tests/agentEngine.test.ts": {
|
||||||
"mtimeMs": 1778690526000,
|
"mtimeMs": 1778690770000,
|
||||||
"size": 33414,
|
"size": 33921,
|
||||||
"lines": 776,
|
"lines": 782,
|
||||||
"role": "AgentEngine Integration Tests & Performance Benchmarks 검증 대상: 1. ErrorClassifier — 오류 유형(Transient/Permanent/Abort) 자동 분류 2. ErrorRecoveryMatrix — 각 규칙이 의도한 대응 전략으로 매핑되는지 검증 3. resilientExecute — 지수 백",
|
"role": "AgentEngine Integration Tests & Performance Benchmarks 검증 대상: 1. ErrorClassifier — 오류 유형(Transient/Permanent/Abort) 자동 분류 2. ErrorRecoveryMatrix — 각 규칙이 의도한 대응 전략으로 매핑되는지 검증 3. resilientExecute — 지수 백",
|
||||||
"imports": [
|
"imports": [
|
||||||
"src/lib/engine"
|
"src/lib/engine"
|
||||||
@@ -1508,7 +1508,7 @@
|
|||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"docs/records/ConnectAI/chronicle.config.json": {
|
"docs/records/ConnectAI/chronicle.config.json": {
|
||||||
"mtimeMs": 1778690568000,
|
"mtimeMs": 1778690673000,
|
||||||
"size": 416,
|
"size": 416,
|
||||||
"lines": 11,
|
"lines": 11,
|
||||||
"role": "JSON configuration",
|
"role": "JSON configuration",
|
||||||
@@ -1717,6 +1717,13 @@
|
|||||||
"role": "Development Log: 너는 분석 요청하거나 내가 작업 요청을 할때 connectai architecture.md 문서를 참고하고 작업을 하나?",
|
"role": "Development Log: 너는 분석 요청하거나 내가 작업 요청을 할때 connectai architecture.md 문서를 참고하고 작업을 하나?",
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
|
"docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업-할-거야.md": {
|
||||||
|
"mtimeMs": 1778690673000,
|
||||||
|
"size": 652,
|
||||||
|
"lines": 16,
|
||||||
|
"role": "Discussion: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 작업 할 거야.",
|
||||||
|
"imports": []
|
||||||
|
},
|
||||||
"docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업할거야.md": {
|
"docs/records/ConnectAI/discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업할거야.md": {
|
||||||
"mtimeMs": 1778680095000,
|
"mtimeMs": 1778680095000,
|
||||||
"size": 651,
|
"size": 651,
|
||||||
@@ -1767,9 +1774,9 @@
|
|||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"docs/records/ConnectAI/timeline.md": {
|
"docs/records/ConnectAI/timeline.md": {
|
||||||
"mtimeMs": 1778689955000,
|
"mtimeMs": 1778690673000,
|
||||||
"size": 8165,
|
"size": 8318,
|
||||||
"lines": 122,
|
"lines": 125,
|
||||||
"role": "Project Timeline",
|
"role": "Project Timeline",
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"result": "Final report with inconsistencies. This should be long enough to pass validation.",
|
"result": "Final report with inconsistencies. This should be long enough to pass validation.",
|
||||||
"createdAt": 1778690820030,
|
"createdAt": 1778691140353,
|
||||||
"modelVersion": "unknown"
|
"modelVersion": "unknown"
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"result": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
|
"result": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
|
||||||
"createdAt": 1778690820030,
|
"createdAt": 1778691140352,
|
||||||
"modelVersion": "unknown"
|
"modelVersion": "unknown"
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"result": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
|
"result": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
|
||||||
"createdAt": 1778690820029,
|
"createdAt": 1778691140352,
|
||||||
"modelVersion": "unknown"
|
"modelVersion": "unknown"
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"result": "---\nid: stress_conflict_1778690820018\ndate: 2026-05-13T16:47:00.031Z\ntype: knowledge_artifact\nstandard: P-Reinforce v3.0\ntags: [automated, connect_ai, brain_sync]\n---\n\n## 📌 Brief Summary\nFinal report with inconsistencies. This should be long enough to pass validation.\n\nFinal report with inconsistencies. This should be long enough to pass validation.\n\n---\n## 💡 Astra의 선제적 제안 (Proactive Next Actions)\nFinal report with inconsistencies. This should be long enough to pass validation.\n---\n## 🛡️ Reliability & Audit Summary\n> [!NOTE]\n> 이 문서는 ConnectAI의 **Intelligent Resilience** 엔진에 의해 검증 및 정제되었습니다.\n\n| Metric | Value | Status |\n| :--- | :--- | :--- |\n| **Conflict Risk** | `60/100` | ⚠️ Medium |\n| **Fallbacks Used** | `0` | ✅ None |\n| **Auto Retries** | `0` | ✅ Stable |\n| **Deduplication** | `0` | Standard |\n| **Processing Time** | `0.0s` | ✅ Fast |\n\n### 🔍 Decision Audit Trail\n- **[PLANNER]** 전략 수립 중... (11ms)\n- **[RESEARCHER]** 핵심 정보 수집 및 분석 중... (0ms)\n- **[WRITER]** 최종 리포트 작성 및 편집 중... (1ms)\n",
|
"result": "---\nid: stress_conflict_1778691140340\ndate: 2026-05-13T16:52:20.353Z\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]** 최종 리포트 작성 및 편집 중... (0ms)\n",
|
||||||
"createdAt": 1778690820031,
|
"createdAt": 1778691140353,
|
||||||
"modelVersion": "unknown"
|
"modelVersion": "unknown"
|
||||||
}
|
}
|
||||||
+8
-8
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"missionId": "stress_conflict_1778690820018",
|
"missionId": "stress_conflict_1778691140340",
|
||||||
"status": "completed",
|
"status": "completed",
|
||||||
"startTime": "2026-05-13T16:47:00.018Z",
|
"startTime": "2026-05-13T16:52:20.340Z",
|
||||||
"totalElapsedMs": 13,
|
"totalElapsedMs": 13,
|
||||||
"results": {
|
"results": {
|
||||||
"planner": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
|
"planner": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
|
||||||
@@ -16,30 +16,30 @@
|
|||||||
{
|
{
|
||||||
"from": "idle",
|
"from": "idle",
|
||||||
"to": "planner",
|
"to": "planner",
|
||||||
"durationMs": 11,
|
"durationMs": 12,
|
||||||
"message": "전략 수립 중...",
|
"message": "전략 수립 중...",
|
||||||
"ts": "2026-05-13T16:47:00.029Z"
|
"ts": "2026-05-13T16:52:20.352Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "planner",
|
"from": "planner",
|
||||||
"to": "researcher",
|
"to": "researcher",
|
||||||
"durationMs": 0,
|
"durationMs": 0,
|
||||||
"message": "핵심 정보 수집 및 분석 중...",
|
"message": "핵심 정보 수집 및 분석 중...",
|
||||||
"ts": "2026-05-13T16:47:00.029Z"
|
"ts": "2026-05-13T16:52:20.352Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "researcher",
|
"from": "researcher",
|
||||||
"to": "writer",
|
"to": "writer",
|
||||||
"durationMs": 1,
|
"durationMs": 0,
|
||||||
"message": "최종 리포트 작성 및 편집 중...",
|
"message": "최종 리포트 작성 및 편집 중...",
|
||||||
"ts": "2026-05-13T16:47:00.030Z"
|
"ts": "2026-05-13T16:52:20.352Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "writer",
|
"from": "writer",
|
||||||
"to": "completed",
|
"to": "completed",
|
||||||
"durationMs": 1,
|
"durationMs": 1,
|
||||||
"message": "미션 완료",
|
"message": "미션 완료",
|
||||||
"ts": "2026-05-13T16:47:00.031Z"
|
"ts": "2026-05-13T16:52:20.353Z"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"resilienceMetrics": {
|
"resilienceMetrics": {
|
||||||
@@ -7,5 +7,5 @@
|
|||||||
"corePurpose": "",
|
"corePurpose": "",
|
||||||
"detailLevel": "standard",
|
"detailLevel": "standard",
|
||||||
"createdAt": "2026-05-13T13:09:33.788Z",
|
"createdAt": "2026-05-13T13:09:33.788Z",
|
||||||
"updatedAt": "2026-05-13T16:44:33.835Z"
|
"updatedAt": "2026-05-13T16:54:16.995Z"
|
||||||
}
|
}
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
# Development Log: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 작업할거야
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Record the implementation or verification outcome from the current conversation.
|
||||||
|
|
||||||
|
## Implementation Summary
|
||||||
|
네, `/Volumes/Data/project/Antigravity/ConnectAI` 프로젝트를 진행하시려는군요. 어떤 부분부터 시작하면 좋을지 구체적인 목표나 첫 번째 작업에 대해 말씀해 주시겠습니까? 예를 들어, 아키텍처 검토, 특정 기능 구현, 혹은 초기 계획 수립 등 원하는 방향을 알려주시면 바로 실행하겠습니다.
|
||||||
|
|
||||||
|
## 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.
|
||||||
@@ -123,3 +123,6 @@
|
|||||||
|
|
||||||
## 2026-05-13
|
## 2026-05-13
|
||||||
- Auto discussion record created: discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업-할-거야.md
|
- Auto discussion record created: discussions/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업-할-거야.md
|
||||||
|
|
||||||
|
## 2026-05-13
|
||||||
|
- Auto development record created: development/2026-05-13_volumes-data-project-antigravity-connectai-이-프로젝트-작업할거야_implementation.md
|
||||||
|
|||||||
@@ -608,6 +608,20 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
if (!provider) return;
|
if (!provider) return;
|
||||||
await provider._openArchitectureDoc();
|
await provider._openArchitectureDoc();
|
||||||
}),
|
}),
|
||||||
|
// Re-resolve the active subproject when the user switches between files
|
||||||
|
// in different subfolders. Debounced so rapid editor flicks don't churn
|
||||||
|
// the chip / watcher. The actual resync is idempotent — if the active
|
||||||
|
// subproject didn't change, nothing visible happens.
|
||||||
|
(() => {
|
||||||
|
let timer: NodeJS.Timeout | undefined;
|
||||||
|
return vscode.window.onDidChangeActiveTextEditor(() => {
|
||||||
|
if (!provider) return;
|
||||||
|
if (timer) clearTimeout(timer);
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
provider!._sendArchitectureStatus().catch(() => { /* swallow — chip is best-effort */ });
|
||||||
|
}, 400);
|
||||||
|
});
|
||||||
|
})(),
|
||||||
// ── 1인 기업 (Company) Mode commands ──────────────────────────────────
|
// ── 1인 기업 (Company) Mode commands ──────────────────────────────────
|
||||||
// Thin shells over sidebar-provider methods so the runtime owns all
|
// Thin shells over sidebar-provider methods so the runtime owns all
|
||||||
// state mutation (chip status, watcher lifecycle, agent persistence).
|
// state mutation (chip status, watcher lifecycle, agent persistence).
|
||||||
|
|||||||
@@ -130,6 +130,56 @@ export function architectureDocPathFor(projectRoot: string): string {
|
|||||||
return path.join(projectRoot, ARCH_DIR_REL, ARCH_FILE);
|
return path.join(projectRoot, ARCH_DIR_REL, ARCH_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the *effective* subproject root when the user has opened a parent
|
||||||
|
* folder that contains several independent subprojects (each carrying its own
|
||||||
|
* `.astra/project-context/` or `package.json`).
|
||||||
|
*
|
||||||
|
* Walks up from `hintFsPath` toward `workspaceRoot` and returns the first
|
||||||
|
* ancestor that already looks like a subproject. Falls back to `workspaceRoot`
|
||||||
|
* when no nested marker is found, when the hint lives outside the workspace,
|
||||||
|
* or when the hint sits inside `node_modules` / build folders.
|
||||||
|
*
|
||||||
|
* Markers (in order):
|
||||||
|
* 1. `.astra/project-context/` — an already-initialised Astra subproject.
|
||||||
|
* 2. `package.json` — a Node project root (covers fresh subprojects that
|
||||||
|
* haven't activated architecture mode yet).
|
||||||
|
*/
|
||||||
|
export function resolveActiveSubprojectRoot(workspaceRoot: string, hintFsPath?: string): string {
|
||||||
|
if (!workspaceRoot || !hintFsPath) return workspaceRoot;
|
||||||
|
let wsNorm: string;
|
||||||
|
let hintNorm: string;
|
||||||
|
try {
|
||||||
|
wsNorm = path.resolve(workspaceRoot);
|
||||||
|
hintNorm = path.resolve(hintFsPath);
|
||||||
|
} catch {
|
||||||
|
return workspaceRoot;
|
||||||
|
}
|
||||||
|
const rel = path.relative(wsNorm, hintNorm);
|
||||||
|
if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) {
|
||||||
|
return workspaceRoot;
|
||||||
|
}
|
||||||
|
// Skip hints that live inside dependency / build folders — those are not
|
||||||
|
// user-authored subprojects, and `node_modules/<pkg>/package.json` would
|
||||||
|
// otherwise be mistaken for a subproject root.
|
||||||
|
const skipSegments = new Set(['node_modules', '.git', 'out', 'dist', '.astra']);
|
||||||
|
const relSegments = rel.split(/[\\/]+/);
|
||||||
|
if (relSegments.some((s) => skipSegments.has(s))) return workspaceRoot;
|
||||||
|
|
||||||
|
let cur = path.dirname(hintNorm);
|
||||||
|
while (true) {
|
||||||
|
if (cur === wsNorm) return workspaceRoot;
|
||||||
|
const r = path.relative(wsNorm, cur);
|
||||||
|
if (!r || r.startsWith('..') || path.isAbsolute(r)) return workspaceRoot;
|
||||||
|
const astraMarker = path.join(cur, ARCH_DIR_REL);
|
||||||
|
const pkgMarker = path.join(cur, 'package.json');
|
||||||
|
if (fs.existsSync(astraMarker) || fs.existsSync(pkgMarker)) return cur;
|
||||||
|
const parent = path.dirname(cur);
|
||||||
|
if (parent === cur) return workspaceRoot;
|
||||||
|
cur = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Backwards-compatible thin wrapper. The watcher / refresh path only needs the
|
* Backwards-compatible thin wrapper. The watcher / refresh path only needs the
|
||||||
* shape-signature to decide whether to re-emit the doc, so we expose `scanProject`
|
* shape-signature to decide whether to re-emit the doc, so we expose `scanProject`
|
||||||
|
|||||||
+18
-2
@@ -31,6 +31,7 @@ import {
|
|||||||
buildOrRefreshArchitectureDoc,
|
buildOrRefreshArchitectureDoc,
|
||||||
architectureDocPathFor,
|
architectureDocPathFor,
|
||||||
formatArchitectureContextForPrompt,
|
formatArchitectureContextForPrompt,
|
||||||
|
resolveActiveSubprojectRoot,
|
||||||
scanProject,
|
scanProject,
|
||||||
} from './features/projectArchitecture';
|
} from './features/projectArchitecture';
|
||||||
import { detectProjectIntent, KnownProject } from './features/projectArchitecture/intentDetector';
|
import { detectProjectIntent, KnownProject } from './features/projectArchitecture/intentDetector';
|
||||||
@@ -1217,8 +1218,14 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
|||||||
* is free.
|
* is free.
|
||||||
*/
|
*/
|
||||||
async _ensureActiveProjectForWorkspace(): Promise<ProjectProfile | null> {
|
async _ensureActiveProjectForWorkspace(): Promise<ProjectProfile | null> {
|
||||||
const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
const wsRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
||||||
if (!workspaceRoot) return null;
|
if (!wsRoot) return null;
|
||||||
|
// When the parent folder contains several subprojects, use the active
|
||||||
|
// editor's location to pick the *effective* subproject root instead of
|
||||||
|
// always reporting the parent.
|
||||||
|
const hint = vscode.window.activeTextEditor?.document.uri.fsPath
|
||||||
|
?? vscode.window.visibleTextEditors[0]?.document.uri.fsPath;
|
||||||
|
const workspaceRoot = resolveActiveSubprojectRoot(wsRoot, hint);
|
||||||
const projects = this._getChronicleProjects();
|
const projects = this._getChronicleProjects();
|
||||||
const active = this._getActiveChronicleProject();
|
const active = this._getActiveChronicleProject();
|
||||||
const norm = (p: string | undefined) => (p || '').replace(/[\\/]+$/, '').toLowerCase();
|
const norm = (p: string | undefined) => (p || '').replace(/[\\/]+$/, '').toLowerCase();
|
||||||
@@ -2484,6 +2491,15 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
|||||||
logError('architecture: intent detection failed.', { error: e?.message ?? String(e) });
|
logError('architecture: intent detection failed.', { error: e?.message ?? String(e) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Re-resolve the active subproject from the currently-focused editor.
|
||||||
|
// Without this, switching between subprojects (e.g. ConnectAI →
|
||||||
|
// Datacollector) inside one VS Code window keeps loading the previous
|
||||||
|
// subproject's architecture into the prompt.
|
||||||
|
try {
|
||||||
|
await this._ensureActiveProjectForWorkspace();
|
||||||
|
} catch (e: any) {
|
||||||
|
logError('architecture: workspace resync failed.', { error: e?.message ?? String(e) });
|
||||||
|
}
|
||||||
const projectArchitectureContext = this._buildProjectArchitectureContext();
|
const projectArchitectureContext = this._buildProjectArchitectureContext();
|
||||||
|
|
||||||
// [File Processing v2] 파일 타입별 분류 처리
|
// [File Processing v2] 파일 타입별 분류 처리
|
||||||
|
|||||||
Reference in New Issue
Block a user