FN-7510: default planner oversight to autonomous
Enable full planner steering/control by default while preserving explicit workflow and task opt-outs. - Document that planner oversight resolves as task override, workflow setting, then autonomous default. - Add regression coverage for built-in workflow defaults, stored workflow overrides, and per-task overrides. - Add a minor changeset for the published Fusion package. Files changed: .changeset/fn-7510-oversight-default.md | 7 ++ docs/workflow-steps.md | 9 ++- .../plannerOversightLevel-default.test.ts | 79 ++++++++++++++++++++++ 3 files changed, 93 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7510 Fusion-Task-Lineage: 2dbf8273-4239-4754-9713-e089f75be930 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7510-oversight-default.md
Normal file
7
.changeset/fn-7510-oversight-default.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": minor
|
||||
---
|
||||
|
||||
summary: Planner oversight now defaults to full steering/control for every workflow unless explicitly changed.
|
||||
category: feature
|
||||
dev: Confirms the `plannerOversightLevel` workflow-setting default is the highest (autonomous) level; unset workflow value and unset per-task override both resolve to full steering via `resolveEffectivePlannerOversightLevel` (task override → workflow effective value → autonomous), adding dedicated regression coverage for the "unless explicitly disabled" precedence.
|
||||
@@ -837,8 +837,13 @@ automatic large-task splitting guidance for oversized M/L work. Set it to `false
|
||||
in a workflow's Values tab when triage should keep large tasks whole unless the
|
||||
task explicitly has `breakIntoSubtasks: true`; explicit subtask requests still
|
||||
follow the mandatory split flow. Planner oversight uses `plannerOversightLevel`
|
||||
(default `autonomous`) with `off`, `observe`, `steer`, and `autonomous` values;
|
||||
per-task override and engine runtime behavior are follow-up work. See
|
||||
(default `autonomous`) with `off`, `observe`, `steer`, and `autonomous` values —
|
||||
full steering/control is ON for every workflow unless explicitly changed. Tasks
|
||||
may set a nullable `Task.plannerOversightLevel` override that wins over the
|
||||
workflow value when present; `resolveEffectivePlannerOversightLevel` in
|
||||
`@fusion/core` resolves the effective level as task override → workflow
|
||||
effective value → `autonomous`. The overseer runtime/monitoring behavior that
|
||||
acts on this level is still follow-up work (FN-7511+). See
|
||||
[Settings Reference → Workflow Settings](./settings-reference.md#workflow-settings)
|
||||
for the full moved-key catalog, the editor walkthrough, and the export/sync posture.
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* FNXC:PlannerOversight 2026-07-04-13:00:
|
||||
* FN-7510 dedicated regression coverage: planner oversight defaults to full
|
||||
* steering/control ("autonomous") for every workflow unless explicitly
|
||||
* disabled at the workflow-setting scope or the per-task override scope.
|
||||
* Precedence is task override -> workflow effective value -> "autonomous"
|
||||
* declaration default (see resolveEffectivePlannerOversightLevel).
|
||||
*/
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
|
||||
import { BUILTIN_OVERSIGHT_SETTINGS, BUILTIN_WORKFLOW_SETTINGS } from "../builtin-workflow-settings.js";
|
||||
import { DEFAULT_PLANNER_OVERSIGHT_LEVEL } from "../types.js";
|
||||
import {
|
||||
resolveEffectiveSettingsById,
|
||||
resolveEffectivePlannerOversightLevel,
|
||||
type WorkflowSettingsResolverStore,
|
||||
} from "../workflow-settings-resolver.js";
|
||||
|
||||
const PROJECT = "proj-1";
|
||||
|
||||
function makeStore(values?: Record<string, unknown>): WorkflowSettingsResolverStore {
|
||||
return {
|
||||
getTaskWorkflowSelection: vi.fn(() => undefined),
|
||||
getWorkflowDefinition: vi.fn(async () => undefined),
|
||||
getWorkflowSettingValues: vi.fn(() => values ?? {}),
|
||||
getWorkflowSettingsProjectId: vi.fn(() => PROJECT),
|
||||
};
|
||||
}
|
||||
|
||||
describe("plannerOversightLevel default (FN-7510)", () => {
|
||||
it("(a) the declaration default is the full-steering value 'autonomous'", () => {
|
||||
const decl = BUILTIN_OVERSIGHT_SETTINGS.find((s) => s.id === "plannerOversightLevel");
|
||||
expect(decl).toBeDefined();
|
||||
expect(decl?.default).toBe("autonomous");
|
||||
expect(decl?.default).toBe(DEFAULT_PLANNER_OVERSIGHT_LEVEL);
|
||||
// The declaration lives in the composed catalog every built-in workflow spreads.
|
||||
expect(BUILTIN_WORKFLOW_SETTINGS.some((s) => s.id === "plannerOversightLevel")).toBe(true);
|
||||
});
|
||||
|
||||
it("(b) resolveEffectiveSettingsById for a built-in workflow with no stored value returns full steering", async () => {
|
||||
const store = makeStore({});
|
||||
const eff = await resolveEffectiveSettingsById(store, "builtin:coding", PROJECT);
|
||||
expect(eff.plannerOversightLevel).toBe("autonomous");
|
||||
});
|
||||
|
||||
it("(c) an explicit stored workflow value overrides the default ('off')", async () => {
|
||||
const store = makeStore({ plannerOversightLevel: "off" });
|
||||
const eff = await resolveEffectiveSettingsById(store, "builtin:coding", PROJECT);
|
||||
expect(eff.plannerOversightLevel).toBe("off");
|
||||
});
|
||||
|
||||
it("(c) an explicit stored workflow value overrides the default ('steer')", async () => {
|
||||
const store = makeStore({ plannerOversightLevel: "steer" });
|
||||
const eff = await resolveEffectiveSettingsById(store, "builtin:coding", PROJECT);
|
||||
expect(eff.plannerOversightLevel).toBe("steer");
|
||||
});
|
||||
|
||||
it("(d) an unset per-task override falls through to the workflow/default level", () => {
|
||||
expect(resolveEffectivePlannerOversightLevel(undefined, "autonomous")).toBe("autonomous");
|
||||
expect(resolveEffectivePlannerOversightLevel(null, "steer")).toBe("steer");
|
||||
});
|
||||
|
||||
it("(d) an explicit per-task override wins over the workflow value", () => {
|
||||
expect(resolveEffectivePlannerOversightLevel("steer", "autonomous")).toBe("steer");
|
||||
expect(resolveEffectivePlannerOversightLevel("off", "autonomous")).toBe("off");
|
||||
});
|
||||
|
||||
it("(e) 'off' is honored at the workflow scope when no task override is set", () => {
|
||||
expect(resolveEffectivePlannerOversightLevel(undefined, "off")).toBe("off");
|
||||
});
|
||||
|
||||
it("(e) 'off' is honored at the per-task scope even when the workflow value is full steering", () => {
|
||||
expect(resolveEffectivePlannerOversightLevel("off", "autonomous")).toBe("off");
|
||||
});
|
||||
|
||||
it("both workflow value and task override unset resolve to full steering (unless-explicitly-disabled)", () => {
|
||||
expect(resolveEffectivePlannerOversightLevel(undefined, undefined)).toBe(DEFAULT_PLANNER_OVERSIGHT_LEVEL);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user