feat(FN-1423): add promptOverrides to project settings

- Add promptOverrides configuration to project settings with null-as-delete semantics
- Add core prompt-key catalog with resolver primitives in packages/core/src/prompt-overrides.ts
- Export prompt key catalog, resolution functions, and settings merge helpers from @fusion/core
- Add parity tests for promptOverrides settings handling
- Add settings export/import coverage for promptOverrides
- Add settings export tests verifying promptOverrides round-trip
- Update settings reference documentation with promptOverrides section
- Add store methods for loading/exporting project settings with prompt overrides
This commit is contained in:
gsxdsm
2026-04-09 18:21:29 -07:00
parent 9b30cc323d
commit a9e8073d2a
9 changed files with 1167 additions and 0 deletions

View File

@@ -872,6 +872,164 @@ describe("TaskStore", () => {
});
});
// ── Prompt Overrides Tests ─────────────────────────────────────────
describe("promptOverrides settings", () => {
it("can set a single prompt override", async () => {
await store.updateSettings({
promptOverrides: { "executor-welcome": "Custom executor welcome message" },
});
const settings = await store.getSettings();
expect(settings.promptOverrides).toEqual({ "executor-welcome": "Custom executor welcome message" });
});
it("can set multiple prompt overrides", async () => {
await store.updateSettings({
promptOverrides: {
"executor-welcome": "Custom welcome",
"triage-welcome": "Custom triage welcome",
},
});
const settings = await store.getSettings();
expect(settings.promptOverrides).toEqual({
"executor-welcome": "Custom welcome",
"triage-welcome": "Custom triage welcome",
});
});
it("promptOverrides is undefined by default", async () => {
const settings = await store.getSettings();
expect(settings.promptOverrides).toBeUndefined();
});
it("can merge new overrides with existing overrides", async () => {
// Set initial overrides
await store.updateSettings({
promptOverrides: { "executor-welcome": "Initial welcome" },
});
// Add more overrides
await store.updateSettings({
promptOverrides: { "triage-welcome": "Custom triage" },
});
const settings = await store.getSettings();
expect(settings.promptOverrides).toEqual({
"executor-welcome": "Initial welcome",
"triage-welcome": "Custom triage",
});
});
it("can update an existing override", async () => {
await store.updateSettings({
promptOverrides: { "executor-welcome": "Original" },
});
await store.updateSettings({
promptOverrides: { "executor-welcome": "Updated" },
});
const settings = await store.getSettings();
expect(settings.promptOverrides).toEqual({ "executor-welcome": "Updated" });
});
it("can clear a specific override with null value", async () => {
// Set initial overrides
await store.updateSettings({
promptOverrides: {
"executor-welcome": "Welcome",
"triage-welcome": "Triage",
},
});
// Clear only executor-welcome
await store.updateSettings({
promptOverrides: { "executor-welcome": null as unknown as string },
});
const settings = await store.getSettings();
expect(settings.promptOverrides).toEqual({ "triage-welcome": "Triage" });
});
it("clears entire promptOverrides when all keys are cleared", async () => {
await store.updateSettings({
promptOverrides: { "executor-welcome": "Welcome" },
});
await store.updateSettings({
promptOverrides: { "executor-welcome": null as unknown as string },
});
const settings = await store.getSettings();
expect(settings.promptOverrides).toBeUndefined();
});
it("can clear entire promptOverrides with null", async () => {
await store.updateSettings({
promptOverrides: { "executor-welcome": "Welcome", "triage-welcome": "Triage" },
});
await store.updateSettings({
promptOverrides: null as unknown as Record<string, string>,
});
const settings = await store.getSettings();
expect(settings.promptOverrides).toBeUndefined();
});
it("persists empty string overrides as cleared (not stored)", async () => {
// Setting an empty string should be treated as "clear" and not persist
await store.updateSettings({
promptOverrides: { "executor-welcome": "" },
});
const settings = await store.getSettings();
expect(settings.promptOverrides).toBeUndefined();
});
it("handles promptOverrides in getSettingsByScope", async () => {
await store.updateSettings({
promptOverrides: { "executor-welcome": "Scoped welcome" },
});
const { project } = await store.getSettingsByScope();
expect(project.promptOverrides).toEqual({ "executor-welcome": "Scoped welcome" });
});
it("preserves other settings when updating promptOverrides", async () => {
await store.updateSettings({
maxConcurrent: 5,
autoMerge: false,
});
await store.updateSettings({
promptOverrides: { "executor-welcome": "Welcome" },
});
const settings = await store.getSettings();
expect(settings.maxConcurrent).toBe(5);
expect(settings.autoMerge).toBe(false);
expect(settings.promptOverrides).toEqual({ "executor-welcome": "Welcome" });
});
it("preserves promptOverrides when updating other settings", async () => {
await store.updateSettings({
promptOverrides: { "executor-welcome": "Welcome", "triage-welcome": "Triage" },
});
await store.updateSettings({ maxConcurrent: 7 });
const settings = await store.getSettings();
expect(settings.maxConcurrent).toBe(7);
expect(settings.promptOverrides).toEqual({
"executor-welcome": "Welcome",
"triage-welcome": "Triage",
});
});
});
// ── Concurrent stress test ───────────────────────────────────────
describe("concurrent stress", () => {