FN-7508: add planner oversight workflow setting

Declare a workflow-native planner oversight level with release notes and docs.

- Add the plannerOversightLevel enum setting with Off, Observe, Steer, and Autonomous recovery values.
- Export the oversight settings catalog and include it in built-in workflow defaults.
- Cover consistency, resolver defaults, and catalog membership with core tests.
- Document the workflow setting and add the published package changeset.

Files changed:
 .../fn-7508-planner-oversight-level-setting.md     |  7 +++++
 docs/settings-reference.md                         |  8 ++++--
 docs/workflow-steps.md                             | 17 +++++++-----
 .../builtin-workflow-settings-triage.test.ts       | 32 ++++++++++++++++++++++
 .../src/__tests__/settings-consistency.test.ts     |  4 ++-
 .../__tests__/workflow-settings-resolver.test.ts   |  1 +
 packages/core/src/builtin-workflow-settings.ts     | 26 ++++++++++++++++++
 packages/core/src/index.ts                         |  1 +
 8 files changed, 86 insertions(+), 10 deletions(-)

Fusion-Task-Id: FN-7508

Fusion-Task-Lineage: 1adc7ce6-9e0e-475e-956a-ee36edae0cdc

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-04 11:26:31 -07:00
parent 2797803c0b
commit 68f5153e17
8 changed files with 86 additions and 10 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": minor
---
summary: Add a per-workflow planner oversight level setting (Off, Observe, Steer, Autonomous recovery).
category: feature
dev: New workflow setting `plannerOversightLevel` declared in BUILTIN_OVERSIGHT_SETTINGS; default `autonomous`. Per-task override and engine behavior land in follow-up tasks.

View File

@@ -280,8 +280,10 @@ Actions. It has two tabs:
controls. Built-in Plan Review/spec and Code Review revision caps also live here:
leave `planReviewMaxRevisions` or `codeReviewMaxRevisions` empty for unbounded
automatic revisions, enter a non-negative integer to cap attempts, or enter `0`
to disable automatic revision for that path. Edits batch and commit through a
single **Save** in the Values tab.
to disable automatic revision for that path. `plannerOversightLevel` is the
workflow-native planner oversight mode and accepts `off`, `observe`, `steer`,
or `autonomous` (default). Edits batch and commit through a single **Save** in
the Values tab.
**How values resolve.** The engine resolves *effective settings* per task as
`stored value ?? declaration default`. The task-detail Workflow, Chat, and Agent
@@ -320,6 +322,7 @@ These groups moved out of project settings and into workflow settings (built-in
|---|---|
| **Step execution** | `workflowStepTimeoutMs`, `runStepsInNewSessions`, `maxParallelSteps`, `workflowStepScopeEnforcement`, `strictScopeEnforcement`, `verificationFixRetries`, `maxPostReviewFixes`, `buildRetryCount` |
| **Review / approval** | Workflow values: `requirePrApproval`, `requirePlanApproval`, `reviewHandoffPolicy`, `maxReviewerContextRetries`, `maxReviewerFallbackRetries`, `planReviewMaxRevisions`, `codeReviewMaxRevisions`; project override: `planApprovalMode` |
| **Planner oversight** | `plannerOversightLevel` (workflow-native; values: `off`, `observe`, `steer`, `autonomous`) |
| **Per-phase model lanes** | `executionProvider`/`executionModelId`, `planningProvider`/`planningModelId` (+ fallbacks), `validatorProvider`/`validatorModelId` (+ fallbacks) |
### Workflow-native triage policy settings
@@ -353,6 +356,7 @@ The built-in workflows also declare triage/spec policy settings that were **not*
| `autoApproveSpec` | `false` | Legacy compatibility setting. Workflow Plan Review now owns optional pre-execution AI plan approval. |
| `planReviewMaxRevisions` | unset | Workflow-native Plan Review/spec revision cap. Unset/empty means unbounded automatic replans; a non-negative integer caps attempts; `0` disables automatic Plan Review revision. |
| `codeReviewMaxRevisions` | unset | Workflow-native Code Review remediation cap. Unset/empty means unbounded automatic code-fix passes; a non-negative integer caps attempts; `0` disables automatic Code Review remediation. |
| `plannerOversightLevel` | `autonomous` | Workflow-native planner oversight mode. `off` disables oversight; `observe` watches only; `steer` injects guidance or suggests revisions; `autonomous` enables bounded retry and targeted-fix recovery. Per-task overrides and engine behavior are follow-up work. |
When `triageProactiveSubtaskSplittingEnabled` is `true` (the default), triage may proactively replace a large task with 2-5 child tasks when the size, step-count, package breadth, file-scope, or remediation-batch signals justify the coordination overhead. When it is `false`, those automatic oversized-task signals are advisory only for writing a realistic single-task spec; triage must not split solely because the task is large. The per-task `breakIntoSubtasks: true` flag is separate and remains mandatory: if a user explicitly asks for subtask breakdown, triage still evaluates and creates child tasks when the work is meaningfully decomposable.

View File

@@ -829,13 +829,16 @@ engine resolves *effective settings* per task as `stored value ?? declaration
default`, dropping any stored value that no longer validates against the current
declaration (drop-on-orphan) and falling back to the default.
The **step-execution**, **review/approval**, **per-phase model-lane**, and
**triage/spec policy** knobs are workflow settings declared by `builtin:coding`.
Triage policy includes `triageProactiveSubtaskSplittingEnabled` (default `true`),
which controls 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. See
The **step-execution**, **review/approval**, **per-phase model-lane**,
**triage/spec policy**, and **planner oversight** knobs are workflow settings
declared by `builtin:coding`. Triage policy includes
`triageProactiveSubtaskSplittingEnabled` (default `true`), which controls
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
[Settings Reference → Workflow Settings](./settings-reference.md#workflow-settings)
for the full moved-key catalog, the editor walkthrough, and the export/sync posture.

View File

@@ -1,6 +1,7 @@
import { describe, expect, it } from "vitest";
import {
BUILTIN_MOVED_WORKFLOW_SETTINGS,
BUILTIN_OVERSIGHT_SETTINGS,
BUILTIN_REVIEW_REVISION_SETTINGS,
BUILTIN_TRIAGE_POLICY_SETTINGS,
BUILTIN_WORKFLOW_SETTINGS,
@@ -80,6 +81,37 @@ describe("workflow-native built-in workflow settings", () => {
}
});
it("declares planner oversight level as a workflow-native enum outside moved/project settings", () => {
const fullIds = new Set(BUILTIN_WORKFLOW_SETTINGS.map((setting) => setting.id));
const movedIds = new Set(BUILTIN_MOVED_WORKFLOW_SETTINGS.map((setting) => setting.id));
const movedKeyIds = new Set(MOVED_SETTINGS_KEYS);
expect(BUILTIN_OVERSIGHT_SETTINGS.map((setting) => setting.id)).toEqual(["plannerOversightLevel"]);
const oversight = BUILTIN_OVERSIGHT_SETTINGS[0];
expect(oversight).toMatchObject({
type: "enum",
default: "autonomous",
});
expect(oversight.options?.map((option) => option.value)).toEqual(["off", "observe", "steer", "autonomous"]);
expect(oversight.options?.map((option) => option.label)).toEqual([
"Off",
"Observe",
"Steer",
"Autonomous recovery",
]);
expect(fullIds.has("plannerOversightLevel"), "plannerOversightLevel should be in the full built-in catalog").toBe(
true,
);
expect(
movedIds.has("plannerOversightLevel"),
"plannerOversightLevel should not be in the moved-key catalog",
).toBe(false);
expect(
movedKeyIds.has("plannerOversightLevel"),
"plannerOversightLevel should not be in MOVED_SETTINGS_KEYS",
).toBe(false);
});
it("renders placeholders from resolved settings and rejects dangling tokens", () => {
const prompt = [
"Size S (<{{triageSizeSmallMaxHours}}h)",

View File

@@ -12,6 +12,7 @@
import { describe, it, expect } from "vitest";
import { MOVED_SETTINGS_KEYS } from "../moved-settings.js";
import {
BUILTIN_OVERSIGHT_SETTINGS,
BUILTIN_REVIEW_REVISION_SETTINGS,
BUILTIN_TRIAGE_POLICY_SETTINGS,
BUILTIN_WORKFLOW_SETTINGS,
@@ -50,11 +51,12 @@ describe("settings consistency (U5)", () => {
const nativeCatalogs = [
{ name: "BUILTIN_TRIAGE_POLICY_SETTINGS", ids: BUILTIN_TRIAGE_POLICY_SETTINGS.map((s) => s.id) },
{ name: "BUILTIN_REVIEW_REVISION_SETTINGS", ids: BUILTIN_REVIEW_REVISION_SETTINGS.map((s) => s.id) },
{ name: "BUILTIN_OVERSIGHT_SETTINGS", ids: BUILTIN_OVERSIGHT_SETTINGS.map((s) => s.id) },
];
const native = new Set(nativeCatalogs.flatMap((catalog) => catalog.ids));
/*
* FNXC:SettingsRegimes 2026-07-02-08:20:
* Workflow-native settings include triage policy and review/revision policy. They must be recognized by the consistency guard without being tombstoned in MOVED_SETTINGS_KEYS or reintroduced into project/global schemas.
* Workflow-native settings include triage policy, review/revision policy, and planner oversight policy. They must be recognized by the consistency guard without being tombstoned in MOVED_SETTINGS_KEYS or reintroduced into project/global schemas.
*/
// Every moved key has a declaration.

View File

@@ -148,6 +148,7 @@ describe("resolveEffectiveSettings (per-task)", () => {
expect(eff[s.id]).toStrictEqual(s.default);
}
}
expect(eff.plannerOversightLevel).toBe("autonomous");
});
it("a stored value for (workflow, project) is returned over the default", async () => {

View File

@@ -21,6 +21,10 @@ import type { WorkflowSettingDefinition } from "./workflow-ir-types.js";
* `BUILTIN_REVIEW_REVISION_SETTINGS` is workflow-native review-loop policy.
* These keys also never lived in project/global settings and intentionally omit
* declaration defaults: an unset workflow value means unbounded remediation.
*
* `BUILTIN_OVERSIGHT_SETTINGS` is workflow-native planner oversight policy.
* These keys never lived in project/global settings and must never be added to
* `MOVED_SETTINGS_KEYS`.
*/
/**
@@ -428,10 +432,32 @@ export const BUILTIN_REVIEW_REVISION_SETTINGS: WorkflowSettingDefinition[] = [
},
];
/**
* FNXC:PlannerOversight 2026-07-04-00:00:
* Workflows declare a default planner oversight level before per-task override and engine reader support land in FN-7509/FN-7510. The workflow-native enum stays out of project settings and `MOVED_SETTINGS_KEYS`; its schema default is `autonomous` so built-in workflows preserve full steering/control until operators choose Off, Observe, or Steer.
*/
export const BUILTIN_OVERSIGHT_SETTINGS: WorkflowSettingDefinition[] = [
{
id: "plannerOversightLevel",
name: "Planner oversight level",
type: "enum",
default: "autonomous",
options: [
{ value: "off", label: "Off" },
{ value: "observe", label: "Observe" },
{ value: "steer", label: "Steer" },
{ value: "autonomous", label: "Autonomous recovery" },
],
description:
"Workflow planner oversight mode: Off disables oversight; Observe watches only; Steer injects guidance or suggests revisions; Autonomous recovery enables bounded retry and targeted-fix recovery.",
},
];
export const BUILTIN_WORKFLOW_SETTINGS: WorkflowSettingDefinition[] = [
...BUILTIN_MOVED_WORKFLOW_SETTINGS,
...BUILTIN_TRIAGE_POLICY_SETTINGS,
...BUILTIN_REVIEW_REVISION_SETTINGS,
...BUILTIN_OVERSIGHT_SETTINGS,
];
const TRIAGE_POLICY_DEFAULTS = new Map(

View File

@@ -187,6 +187,7 @@ export {
BUILTIN_WORKFLOW_SETTINGS,
BUILTIN_MOVED_WORKFLOW_SETTINGS,
BUILTIN_TRIAGE_POLICY_SETTINGS,
BUILTIN_OVERSIGHT_SETTINGS,
renderTriagePolicyPlaceholders,
} from "./builtin-workflow-settings.js";
export {