Release v2.1.2: Chronicle Repair & Context Stability improvements
This commit is contained in:
+72
-3
@@ -982,6 +982,64 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
await this._context.globalState.update(SidebarChatProvider.chronicleProjectsStateKey, projects);
|
||||
}
|
||||
|
||||
/**
|
||||
* One-time repair for chronicle projects that were stored before the
|
||||
* multi-subproject fix landed.
|
||||
*
|
||||
* Old activation code always treated `workspaceFolders[0]` (= the open
|
||||
* parent folder, e.g. `/.../Antigravity`) as the project root, so every
|
||||
* subproject the user activated (`ConnectAI`, `Datacollector_MAC`,
|
||||
* `Skybound`, …) ended up with `projectRoot === <parent>` in globalState.
|
||||
* That breaks reload: `_ensureActiveProjectForWorkspace` case 2 matches
|
||||
* the corrupted entry on every boot and force-switches the active
|
||||
* project to whichever bad row it found first.
|
||||
*
|
||||
* The repair: for each chronicle project whose `projectName` does NOT
|
||||
* match the basename of its stored `projectRoot` (i.e. it can't actually
|
||||
* be the project root), and where a same-name subfolder exists under
|
||||
* the current workspace, retarget the entry to that subfolder. Idempotent
|
||||
* — re-running it after the first pass changes nothing.
|
||||
*/
|
||||
async _repairCorruptedChronicleProjectRoots(): Promise<void> {
|
||||
const wsRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
||||
if (!wsRoot) return;
|
||||
const projects = this._getChronicleProjects();
|
||||
if (projects.length === 0) return;
|
||||
const norm = (p: string | undefined) => (p || '').replace(/[\\/]+$/, '').toLowerCase();
|
||||
const wsRootNorm = norm(wsRoot);
|
||||
let changed = false;
|
||||
const repaired = projects.map((p) => {
|
||||
if (!p.projectName || !p.projectRoot) return p;
|
||||
const rootBase = path.basename(p.projectRoot).toLowerCase();
|
||||
const nameMatches = rootBase === p.projectName.toLowerCase();
|
||||
if (nameMatches) return p; // root basename agrees with name → trust it
|
||||
// Only repair entries that look like they were silently captured at
|
||||
// the workspace parent. Anything else (different machine, custom
|
||||
// path) we leave alone.
|
||||
if (norm(p.projectRoot) !== wsRootNorm) return p;
|
||||
const candidate = path.join(wsRoot, p.projectName);
|
||||
try {
|
||||
if (!fs.existsSync(candidate) || !fs.statSync(candidate).isDirectory()) return p;
|
||||
} catch {
|
||||
return p;
|
||||
}
|
||||
const newDocPath = path.join(candidate, '.astra', 'project-context', 'architecture.md');
|
||||
changed = true;
|
||||
return {
|
||||
...p,
|
||||
projectRoot: candidate,
|
||||
recordRoot: path.join(candidate, 'docs', 'records', p.projectName),
|
||||
architectureDocPath: fs.existsSync(newDocPath) ? newDocPath : p.architectureDocPath,
|
||||
};
|
||||
});
|
||||
if (!changed) return;
|
||||
await this._putChronicleProjects(repaired);
|
||||
const fixedCount = repaired.filter((p, i) => p !== projects[i]).length;
|
||||
logInfo('architecture: repaired chronicle projects with wrong projectRoot.', {
|
||||
wsRoot, count: fixedCount,
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Project Architecture Context (Feature 2) ──────────────────────────────
|
||||
//
|
||||
// Activation flow:
|
||||
@@ -1225,10 +1283,21 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
// 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 active = this._getActiveChronicleProject();
|
||||
const resolved = resolveActiveSubprojectRoot(wsRoot, hint);
|
||||
const norm = (p: string | undefined) => (p || '').replace(/[\\/]+$/, '').toLowerCase();
|
||||
const active = this._getActiveChronicleProject();
|
||||
const projects = this._getChronicleProjects();
|
||||
// Did the editor hint actually point at a nested subproject? If the
|
||||
// resolver fell back to the workspace root (no nested marker, or the
|
||||
// Astra sidebar itself was focused so no editor existed), we must NOT
|
||||
// clobber the user's current active project — they may have set it by
|
||||
// hand via the project picker, or by typing a project intent. Auto-
|
||||
// switching is only safe when there is a clear editor-driven signal.
|
||||
const isNestedHit = !!resolved && norm(resolved) !== norm(wsRoot);
|
||||
if (!isNestedHit && active) {
|
||||
return active;
|
||||
}
|
||||
const workspaceRoot = isNestedHit ? resolved : wsRoot;
|
||||
if (active && active.projectRoot && norm(active.projectRoot) === norm(workspaceRoot)) {
|
||||
return active;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user