fix: cmux library directory incorrectly loaded as extension (#1537)
* fix(#1526): auto-mode worktree commits land on main instead of milestone branch GitServiceImpl.getMainBranch() was designed to detect manual /worktree worktrees (worktree/<name> branches) but incorrectly applied the same logic to auto-mode worktrees (milestone/<MID> branches). When no worktree/<name> branch existed, it fell back to the current branch, which in certain contexts could be main, causing slice commits to land on main instead of the milestone branch. Fix: Detect if currently on a milestone/* branch first (auto-mode case) and return it, before checking for worktree/* branches (manual worktree case). - Modify getMainBranch() to detect milestone branches first - Add test verifying getMainBranch() returns correct branch in auto-worktree - All tests pass, build succeeds Fixes #1526 * fix: cmux library directory incorrectly loaded as extension The extension auto-discovery in resolveExtensionEntries() finds index.js files in subdirectories and treats them as extensions. The cmux directory has an index.js but it's a utility library (imported by gsd and subagent extensions), not an extension itself. Two changes: 1. When a package.json has a "pi" manifest, treat it as authoritative and don't fall through to index.ts/index.js auto-detection. This lets library directories opt out with "pi": {}. 2. Add package.json to cmux directory with empty pi manifest.
This commit is contained in:
parent
aa8d3ee059
commit
71c3b12e70
3 changed files with 40 additions and 5 deletions
|
|
@ -495,7 +495,13 @@ function resolveExtensionEntries(dir: string): string[] | null {
|
|||
const packageJsonPath = path.join(dir, "package.json");
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
const manifest = readPiManifest(packageJsonPath);
|
||||
if (manifest?.extensions?.length) {
|
||||
if (manifest) {
|
||||
// When a pi manifest exists, it is authoritative — don't fall through
|
||||
// to index.ts/index.js auto-detection. This allows library directories
|
||||
// (like cmux) to opt out by declaring "pi": {} with no extensions.
|
||||
if (!manifest.extensions?.length) {
|
||||
return null;
|
||||
}
|
||||
const entries: string[] = [];
|
||||
for (const extPath of manifest.extensions) {
|
||||
const resolvedExtPath = path.resolve(dir, extPath);
|
||||
|
|
@ -503,9 +509,7 @@ function resolveExtensionEntries(dir: string): string[] | null {
|
|||
entries.push(resolvedExtPath);
|
||||
}
|
||||
}
|
||||
if (entries.length > 0) {
|
||||
return entries;
|
||||
}
|
||||
return entries.length > 0 ? entries : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
7
src/resources/extensions/cmux/package.json
Normal file
7
src/resources/extensions/cmux/package.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "@gsd/cmux",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "cmux integration library — used by other extensions, not an extension itself",
|
||||
"pi": {}
|
||||
}
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
import test from "node:test";
|
||||
import test, { describe } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import {
|
||||
buildCmuxProgress,
|
||||
buildCmuxStatusLabel,
|
||||
|
|
@ -96,3 +99,24 @@ test("buildCmuxStatusLabel and progress prefer deepest active unit", () => {
|
|||
assert.equal(buildCmuxStatusLabel(state), "M001 S02/T03 · executing");
|
||||
assert.deepEqual(buildCmuxProgress(state), { value: 0.4, label: "2/5 tasks" });
|
||||
});
|
||||
|
||||
describe("cmux extension discovery opt-out", () => {
|
||||
test("cmux directory has package.json with pi manifest to prevent auto-discovery as extension", () => {
|
||||
const cmuxDir = path.resolve(
|
||||
path.dirname(fileURLToPath(import.meta.url)),
|
||||
"../../cmux",
|
||||
);
|
||||
const pkgPath = path.join(cmuxDir, "package.json");
|
||||
assert.ok(fs.existsSync(pkgPath), `${pkgPath} must exist`);
|
||||
|
||||
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
||||
assert.ok(
|
||||
pkg.pi !== undefined && typeof pkg.pi === "object",
|
||||
'package.json must have a "pi" field to opt out of extension auto-discovery',
|
||||
);
|
||||
assert.ok(
|
||||
!pkg.pi.extensions?.length,
|
||||
"pi.extensions must be empty or absent — cmux is a library, not an extension",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue