mirror of
https://github.com/morluto/rea
synced 2026-10-25 14:01:13 -04:00
fix(update): retain FreeBuff when ZCode reads the shared fallback
Maintenance deduplicated clients on the path each inspection read, so ZCode's fallback view of ~/.agents/mcp.json marked that file "covered" and dropped FreeBuff from the scope. ZCode setup writes ~/.zcode/cli/config.json and deliberately leaves the fallback untouched (docs/client-configuration.md), so the emitted command refreshed only ZCode while the shared row both products load stayed pinned to the old package version. Each setup action rewrites only its own configuration path and no other action rewrites the shared row, so every selected client keeps its own maintenance action; the read-path covered/deduped filter is removed. Covers the Codex P2 on UpdateMaintenance.ts:104. Validation: the new regression fails one2fdec384with {clients:["zcode"]} and passes with {clients:["freebuff","zcode"]}; updateMaintenance 31/31, setupClientConfigCleanupOwnership, cliUpdateAlias, updateOutput, cliStartupImports green; tsc --noEmit, oxlint (0 errors) and oxfmt --check clean; clientRegistrationStatus keeps the same 4 symlink/stale-vs-aligned failures this Windows host has on basee2fdec384(verified by stashing the change). 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
This commit is contained in:
@@ -3,7 +3,6 @@ import { RegularFileCleanupFailure } from "./RegularFileRead.js";
|
||||
|
||||
import { classifyClientRegistrationCommand } from "./ClientRegistrationIdentity.js";
|
||||
import { readClientRegistrationInspections } from "./ClientRegistrationStatus.js";
|
||||
import { supportedClients } from "./SupportedClients.js";
|
||||
import { existingSkillDestinations } from "./SetupSkill.js";
|
||||
import type { SetupAction } from "./SetupTypes.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
@@ -77,32 +76,14 @@ export const existingMaintenanceScope = async (
|
||||
continue;
|
||||
clients.push(registration.client);
|
||||
}
|
||||
// One shared file is one maintenance decision: a shared-registration client
|
||||
// defers to another selected client covering the same file, so the owned
|
||||
// row is refreshed once through the applicable product instead of twice
|
||||
// through two views of the same registration.
|
||||
const shared = new Map(
|
||||
supportedClients(home, process.platform, environment).map((client) => [
|
||||
client.name,
|
||||
client.sharedRegistration === true,
|
||||
]),
|
||||
);
|
||||
const covered = new Set(
|
||||
registrations
|
||||
.filter(
|
||||
({ status }) =>
|
||||
clients.includes(status.client) && shared.get(status.client) !== true,
|
||||
)
|
||||
.map(({ status }) => status.config_path),
|
||||
);
|
||||
const deduped = clients.filter(
|
||||
(client) =>
|
||||
shared.get(client) !== true ||
|
||||
!registrations.some(
|
||||
({ status }) =>
|
||||
status.client === client && covered.has(status.config_path),
|
||||
),
|
||||
);
|
||||
// Each setup action rewrites only that client's own configuration path, so
|
||||
// maintenance keeps every selected client instead of deferring one view of
|
||||
// a registration to another client's inspection: ZCode writes
|
||||
// ~/.zcode/cli/config.json and deliberately leaves the ~/.agents/mcp.json
|
||||
// fallback untouched (docs/client-configuration.md), while FreeBuff writes
|
||||
// the shared file itself. Dropping FreeBuff because ZCode reads that
|
||||
// fallback would leave the row both products load pinned to the old
|
||||
// version.
|
||||
const skillDestinations = await existingSkillDestinations(
|
||||
home,
|
||||
environment,
|
||||
@@ -110,7 +91,7 @@ export const existingMaintenanceScope = async (
|
||||
resources,
|
||||
);
|
||||
return {
|
||||
clients: deduped,
|
||||
clients,
|
||||
skill: skillDestinations.length > 0,
|
||||
skillDestinations,
|
||||
};
|
||||
|
||||
@@ -158,9 +158,11 @@ describe("maintenance activation and layered configuration", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
// The fallback row is also FreeBuff's registration, and FreeBuff is the
|
||||
// setup action that rewrites it, so both views stay in maintenance scope.
|
||||
await expect(
|
||||
existingMaintenanceScope(home, entryPoint, process.env),
|
||||
).resolves.toMatchObject({ clients: ["zcode"] });
|
||||
).resolves.toMatchObject({ clients: ["freebuff", "zcode"] });
|
||||
});
|
||||
|
||||
it("selects an enabled registration inherited through layered OpenCode files", async () => {
|
||||
@@ -355,6 +357,30 @@ describe("shared registration maintenance", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("retains FreeBuff when ZCode reads the shared fallback", async () => {
|
||||
// Both products load the one shared row, but their setup actions write
|
||||
// different files: ZCode writes ~/.zcode/cli/config.json and deliberately
|
||||
// leaves ~/.agents/mcp.json untouched (docs/client-configuration.md), so
|
||||
// its fallback view cannot cover FreeBuff's registration. The shared row
|
||||
// would stay pinned to the old version without FreeBuff's own action.
|
||||
await writeClient("zcode", JSON.stringify({ mcp: { servers: {} } }));
|
||||
await mkdir(join(home, ".config", "freebuff-desktop"), {
|
||||
recursive: true,
|
||||
});
|
||||
await writeClient(
|
||||
"freebuff",
|
||||
JSON.stringify({
|
||||
mcpServers: {
|
||||
rea: { command: "npx", args: ["-y", "rea-agents@0.1.0", "mcp"] },
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(
|
||||
existingMaintenanceScope(home, entryPoint, process.env),
|
||||
).resolves.toMatchObject({ clients: ["freebuff", "zcode"] });
|
||||
});
|
||||
|
||||
it("leaves a foreign shared registration out of maintenance", async () => {
|
||||
await writeClient(
|
||||
"freebuff",
|
||||
|
||||
Reference in New Issue
Block a user