Skip to content

Commit f1e62ec

Browse files
NagyViktNagyVikt
andauthored
Purge stale Active Agents SCM installs (#420)
Older lowercase VS Code companion installs kept registering the removed Active Agents Commit Source Control provider even after the repo extension stopped creating it. The installer now deletes retired lowercase install IDs before refreshing the current Recodee companion copies, so already-open windows cannot keep loading that stale provider path after reload. Constraint: VS Code may keep multiple local extension IDs under ~/.vscode/extensions and load stale publisher/name variants. Rejected: Re-add a runtime Source Control hide shim | the current extension no longer creates a SourceControl object, so stale installed copies were the cause. Confidence: high Scope-risk: narrow Directive: Keep retired extension ID cleanup when publisher/name casing changes; stale local install folders can survive normal compatibility refreshes. Tested: node --test test/vscode-active-agents-session-state.test.js Tested: diff -u scripts/install-vscode-active-agents-extension.js templates/scripts/install-vscode-active-agents-extension.js Tested: node scripts/install-vscode-active-agents-extension.js removed 20 retired local install paths Not-tested: node --test test/metadata.test.js remains red on unrelated README release-note/version expectations and existing Active Agents extension/template drift Co-authored-by: NagyVikt <nagy.viktordp@gmail.com>
1 parent 5bf27a5 commit f1e62ec

4 files changed

Lines changed: 60 additions & 0 deletions

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Remove stale Active Agents SCM providers
2+
3+
## Intent
4+
5+
Prevent old locally installed `recodeee.gitguardex-active-agents*` companion copies from continuing to register the removed `Active Agents Commit` Source Control providers.
6+
7+
## Scope
8+
9+
- Update the VS Code companion installer to delete retired extension IDs before installing the current `Recodee.gitguardex-active-agents` copy.
10+
- Keep `scripts/` and `templates/scripts/` installer copies in sync.
11+
- Extend the focused Active Agents extension test to cover retired install cleanup.
12+
13+
## Verification
14+
15+
- Passed: `node --test test/vscode-active-agents-session-state.test.js` (`55/55`).
16+
- Passed: `node scripts/install-vscode-active-agents-extension.js` removed 20 retired lowercase local install paths.
17+
- Passed: no remaining `recodeee.gitguardex-active-agents*` folders under `/home/deadpool/.vscode/extensions`.
18+
- Passed: no `createSourceControl` or `Active Agents Commit` matches in current installed `Recodee.gitguardex-active-agents` copies checked.
19+
- Baseline red: `node --test test/metadata.test.js` still fails unrelated README release-note/version expectations and pre-existing `vscode/guardex-active-agents/extension.js` template drift.

scripts/install-vscode-active-agents-extension.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ const os = require('node:os');
55
const path = require('node:path');
66

77
const PATCH_COMPATIBILITY_WINDOW = 20;
8+
const RETIRED_EXTENSION_IDS = [
9+
'recodeee.gitguardex-active-agents',
10+
];
811

912
function parseOptions(argv) {
1013
const options = {};
@@ -65,6 +68,12 @@ function buildInstallTargets(extensionId, version, extensionsDir) {
6568
return targets;
6669
}
6770

71+
function isRetiredExtensionInstall(entryName, currentExtensionId) {
72+
return RETIRED_EXTENSION_IDS
73+
.filter((extensionId) => extensionId !== currentExtensionId)
74+
.some((extensionId) => entryName === extensionId || entryName.startsWith(`${extensionId}-`));
75+
}
76+
6877
function main() {
6978
const repoRoot = path.resolve(__dirname, '..');
7079
const options = parseOptions(process.argv.slice(2));
@@ -82,11 +91,17 @@ function main() {
8291
const targetDirs = buildInstallTargets(extensionId, manifest.version, extensionsDir);
8392
const canonicalTargetDir = targetDirs[0];
8493
const keepDirNames = new Set(targetDirs.map((targetDir) => path.basename(targetDir)));
94+
let retiredInstallCount = 0;
8595

8696
for (const entry of fs.readdirSync(extensionsDir, { withFileTypes: true })) {
8797
if (!entry.isDirectory()) {
8898
continue;
8999
}
100+
if (isRetiredExtensionInstall(entry.name, extensionId)) {
101+
removeIfExists(path.join(extensionsDir, entry.name));
102+
retiredInstallCount += 1;
103+
continue;
104+
}
90105
if (keepDirNames.has(entry.name)) {
91106
continue;
92107
}
@@ -107,6 +122,7 @@ function main() {
107122
process.stdout.write(
108123
`[guardex-active-agents] Installed ${extensionId}@${manifest.version} to ${canonicalTargetDir}\n` +
109124
`[guardex-active-agents] Refreshed ${targetDirs.length - 1} recent patch compatibility path(s) for already-open windows.\n` +
125+
`[guardex-active-agents] Removed ${retiredInstallCount} retired extension install path(s).\n` +
110126
'[guardex-active-agents] Reload each already-open VS Code window to activate the newest Source Control companion.\n',
111127
);
112128
}

templates/scripts/install-vscode-active-agents-extension.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ const os = require('node:os');
55
const path = require('node:path');
66

77
const PATCH_COMPATIBILITY_WINDOW = 20;
8+
const RETIRED_EXTENSION_IDS = [
9+
'recodeee.gitguardex-active-agents',
10+
];
811

912
function parseOptions(argv) {
1013
const options = {};
@@ -65,6 +68,12 @@ function buildInstallTargets(extensionId, version, extensionsDir) {
6568
return targets;
6669
}
6770

71+
function isRetiredExtensionInstall(entryName, currentExtensionId) {
72+
return RETIRED_EXTENSION_IDS
73+
.filter((extensionId) => extensionId !== currentExtensionId)
74+
.some((extensionId) => entryName === extensionId || entryName.startsWith(`${extensionId}-`));
75+
}
76+
6877
function main() {
6978
const repoRoot = path.resolve(__dirname, '..');
7079
const options = parseOptions(process.argv.slice(2));
@@ -82,11 +91,17 @@ function main() {
8291
const targetDirs = buildInstallTargets(extensionId, manifest.version, extensionsDir);
8392
const canonicalTargetDir = targetDirs[0];
8493
const keepDirNames = new Set(targetDirs.map((targetDir) => path.basename(targetDir)));
94+
let retiredInstallCount = 0;
8595

8696
for (const entry of fs.readdirSync(extensionsDir, { withFileTypes: true })) {
8797
if (!entry.isDirectory()) {
8898
continue;
8999
}
100+
if (isRetiredExtensionInstall(entry.name, extensionId)) {
101+
removeIfExists(path.join(extensionsDir, entry.name));
102+
retiredInstallCount += 1;
103+
continue;
104+
}
90105
if (keepDirNames.has(entry.name)) {
91106
continue;
92107
}
@@ -107,6 +122,7 @@ function main() {
107122
process.stdout.write(
108123
`[guardex-active-agents] Installed ${extensionId}@${manifest.version} to ${canonicalTargetDir}\n` +
109124
`[guardex-active-agents] Refreshed ${targetDirs.length - 1} recent patch compatibility path(s) for already-open windows.\n` +
125+
`[guardex-active-agents] Removed ${retiredInstallCount} retired extension install path(s).\n` +
110126
'[guardex-active-agents] Reload each already-open VS Code window to activate the newest Source Control companion.\n',
111127
);
112128
}

test/vscode-active-agents-session-state.test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,11 +1217,17 @@ test('install-vscode-active-agents-extension installs the current extension into
12171217
? path.join(tempExtensionsDir, `${extensionId}-${major}.${minor}.${patch - 1}`)
12181218
: currentVersionDir;
12191219
const farLegacyDir = path.join(tempExtensionsDir, `${extensionId}-99.99.99`);
1220+
const retiredLegacyDir = path.join(tempExtensionsDir, 'recodeee.gitguardex-active-agents');
1221+
const retiredLegacyVersionDir = path.join(tempExtensionsDir, 'recodeee.gitguardex-active-agents-0.0.18');
12201222

12211223
fs.mkdirSync(recentCompatDir, { recursive: true });
12221224
fs.writeFileSync(path.join(recentCompatDir, 'stale.txt'), 'old', 'utf8');
12231225
fs.mkdirSync(farLegacyDir, { recursive: true });
12241226
fs.writeFileSync(path.join(farLegacyDir, 'stale.txt'), 'old', 'utf8');
1227+
fs.mkdirSync(retiredLegacyDir, { recursive: true });
1228+
fs.writeFileSync(path.join(retiredLegacyDir, 'extension.js'), 'vscode.scm.createSourceControl();\n', 'utf8');
1229+
fs.mkdirSync(retiredLegacyVersionDir, { recursive: true });
1230+
fs.writeFileSync(path.join(retiredLegacyVersionDir, 'extension.js'), 'vscode.scm.createSourceControl();\n', 'utf8');
12251231

12261232
const result = runNode(installScript, ['--extensions-dir', tempExtensionsDir], {
12271233
cwd: repoRoot,
@@ -1244,8 +1250,11 @@ test('install-vscode-active-agents-extension installs the current extension into
12441250
assert.equal(fs.existsSync(path.join(recentCompatDir, 'package.json')), true);
12451251
assert.equal(fs.existsSync(path.join(recentCompatDir, 'stale.txt')), false);
12461252
assert.equal(fs.existsSync(farLegacyDir), false);
1253+
assert.equal(fs.existsSync(retiredLegacyDir), false);
1254+
assert.equal(fs.existsSync(retiredLegacyVersionDir), false);
12471255
assert.match(result.stdout, new RegExp(`Installed ${extensionId}@${manifest.version} to ${canonicalDir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`));
12481256
assert.match(result.stdout, /Refreshed \d+ recent patch compatibility path\(s\)/);
1257+
assert.match(result.stdout, /Removed 2 retired extension install path\(s\)/);
12491258
assert.match(result.stdout, /Reload each already-open VS Code window/);
12501259
});
12511260

0 commit comments

Comments
 (0)