docs: devlog 011 + known-issues (workspace URI 세션 격리)
This commit is contained in:
@@ -321,3 +321,9 @@
|
||||
- **해결**: `writePendingApproval()`에서 `step_type === 'file_permission'` && `!buttons`일 때 자동으로 3-button 배열 주입
|
||||
- **주의**: DOM observer 경로는 기존 command 텍스트 기반 감지 유지. step_probe 경로만 수정
|
||||
|
||||
### [2026-03-10] GetAllCascadeTrajectories — 크로스 윈도우 세션 가로채기
|
||||
- **증상**: Deriva AG에서 대화 시작 → Discord에 신호 안 잡힘, gravity_control 채널에 Deriva 내용이 릴레이됨
|
||||
- **원인**: `GetAllCascadeTrajectories` RPC가 **모든 AG 인스턴스의 세션**을 반환. 기존 register 파일 기반 필터링은 새 세션(아직 register 없음)에 대해 먼저 폴링한 인스턴스가 `bestSession`으로 가져감. gravity_control extension이 Deriva 세션을 자기 것으로 등록
|
||||
- **해결**: `trajectoryMetadata.workspaces[0].workspaceFolderAbsoluteUri`를 `vscode.workspace.workspaceFolders[0].uri.fsPath`와 비교하여 자기 workspace 세션만 처리. register 파일은 metadata 없는 레거시 세션용 fallback으로 유지
|
||||
- **주의**: workspace URI는 `file:///c:/Users/...` 형식이므로 normalize 필수 (protocol strip, %3A decode, 슬래시 통일, lowercase). 양쪽 AG 풀 재시작 필요
|
||||
|
||||
|
||||
@@ -12,3 +12,4 @@
|
||||
| 008 | 16:45~17:20 | Single active project lock + stale REJECT 필터 + Vikunja 태스크 정리 | `186875a`~`95d4f85` | ✅ |
|
||||
| 009 | 17:20~17:47 | v0.3.6 릴리스 — VSIX 빌드 + start_bot.bat 런처 | `bd46bea` | ✅ |
|
||||
| 010 | 18:00~18:30 | v0.3.7 — file_permission 3-button 주입 + active_project.lock 제거 (멀티프로젝트) | `27deb2a` | ✅ |
|
||||
| 011 | 18:50~19:29 | v0.3.8 — workspace URI 기반 세션 필터링 (멀티프로젝트 격리 완성) | `ae91134` | ✅ |
|
||||
|
||||
@@ -73,6 +73,7 @@ let sdk;
|
||||
let statusBar;
|
||||
let bridgePath;
|
||||
let projectName;
|
||||
let workspaceUri = ''; // filesystem path of the workspace folder (for session filtering)
|
||||
let isActive = false;
|
||||
let deterministicPort = 0; // derived from projectName, consistent across restarts
|
||||
let watcher = null;
|
||||
@@ -1472,14 +1473,32 @@ function setupMonitor() {
|
||||
return;
|
||||
}
|
||||
// ── Filter to sessions owned by THIS window ──
|
||||
// Each window claims sessions it sees first via writeRegistration().
|
||||
// Only process sessions registered to THIS projectName (or unclaimed ones).
|
||||
// PRIMARY: Use trajectoryMetadata.workspaces URI to match sessions to this workspace.
|
||||
// FALLBACK: Use bridge/register/ files for sessions without metadata.
|
||||
// This prevents cross-window session grabbing when multiple AG instances run.
|
||||
let bestSession = null;
|
||||
let bestSessionId = '';
|
||||
let bestModTime = '';
|
||||
const regDir = path.join(bridgePath, 'register');
|
||||
const normalizedWorkspace = workspaceUri.replace(/\\/g, '/').toLowerCase();
|
||||
for (const [sid, data] of Object.entries(allTraj.trajectorySummaries)) {
|
||||
// Check if this session is claimed by another project
|
||||
// PRIMARY FILTER: Check workspace URI from trajectoryMetadata
|
||||
const trajMeta = data.trajectoryMetadata;
|
||||
if (trajMeta?.workspaces?.length > 0 && normalizedWorkspace) {
|
||||
const sessionWorkspaceRaw = trajMeta.workspaces[0]?.workspaceFolderAbsoluteUri || '';
|
||||
// Convert file:///c:/Users/... URI to c:/Users/... path for comparison
|
||||
const sessionWorkspace = sessionWorkspaceRaw
|
||||
.replace(/^file:\/\/\//, '')
|
||||
.replace(/%3A/gi, ':')
|
||||
.replace(/\\/g, '/')
|
||||
.toLowerCase();
|
||||
if (sessionWorkspace && !sessionWorkspace.includes(normalizedWorkspace) && !normalizedWorkspace.includes(sessionWorkspace)) {
|
||||
// Session belongs to a different workspace — skip
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// FALLBACK: Check registration file (for sessions without metadata)
|
||||
const regFile = path.join(regDir, `${sid}.json`);
|
||||
if (fs.existsSync(regFile)) {
|
||||
try {
|
||||
@@ -1491,6 +1510,7 @@ function setupMonitor() {
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
const modTime = data.lastModifiedTime || '';
|
||||
if (!bestSession || modTime > bestModTime) {
|
||||
bestSession = data;
|
||||
@@ -2737,7 +2757,10 @@ async function activate(context) {
|
||||
console.log('Gravity Bridge: activating...');
|
||||
// Project detection
|
||||
projectName = detectProjectName();
|
||||
console.log(`Gravity Bridge: project "${projectName}"`);
|
||||
// Store workspace folder path for session filtering (prevents cross-window session grabbing)
|
||||
const folders = vscode.workspace.workspaceFolders;
|
||||
workspaceUri = folders && folders.length > 0 ? folders[0].uri.fsPath : '';
|
||||
console.log(`Gravity Bridge: project "${projectName}" workspace="${workspaceUri}"`);
|
||||
// Bridge path
|
||||
const config = vscode.workspace.getConfiguration('gravityBridge');
|
||||
const configPath = config.get('bridgePath');
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user