Files
fusion/packages/core/src/session-advisor.ts
gsxdsm 4f037679ad feat: planner overseer session advisor (OMP advisor parity) (#2082)
## Summary

Adds a **session advisor** to the planner overseer so Fusion can review
live executor transcripts the way [oh-my-pi’s
advisor](https://github.com/can1357/oh-my-pi/tree/main/packages/coding-agent/src/advisor)
does — without replacing the existing lifecycle supervisor (stage watch,
retry, merge confirmation, human-control withhold).

### What ships

- **Emission guard** (`OverseerEmissionGuard`) — content-free phrase
filter, session dedupe with severity-rank escalation, one accept per
advisor update
- **Session delta runtime** — queues agent-log deltas, drains through an
advisor agent, drops backlog after 3 failures
- **Session advisor service** — model gate, level matrix (`observe` /
`steer` / `autonomous`), human-control re-check at inject,
`[session-advisor]` steering comments
- **OVERSEER.md / WATCHDOG.md** discovery for project review priorities
- **AgentLogger `onEntriesFlushed`** + poll-backed agent-log cursor for
durable deltas
- Workflow settings: `plannerOverseerAdvisorProvider` +
`plannerOverseerAdvisorModelId` (both required; empty = soft-disabled
for cost safety)
- Docs + changeset

### What does not ship (deferred)

- Multi-advisor YAML roster, mutating advisor tools, reviewer/merger
shadowing, true tool-abort interrupt

### Plan

`docs/plans/2026-07-13-001-feat-overseer-advisor-parity-plan.md`

## Enablement

1. Set workflow **Session advisor model provider** + **Session advisor
model id**
2. Oversight level `observe` (log only), `steer`, or `autonomous`
(inject)
3. Optional: add `OVERSEER.md` or `WATCHDOG.md` in the project

## Test plan

- [x] `pnpm --filter @fusion/core exec vitest run
src/__tests__/overseer-emission-guard.test.ts`
- [x] `pnpm --filter @fusion/engine exec vitest run` overseer-* unit
tests (21 tests)
- [x] Related planner-overseer / intervention regression tests
- [x] `@fusion/engine` + `@fusion/core` typecheck
- [ ] Manual: configure advisor model, run an executor task, confirm
`[session-advisor]` inject + timeline metadata when concern is raised

## Residual Review Findings

None from autofix pass (log-cursor ordering fix already committed).


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added an off-by-default “session advisor” that can review live
execution activity and provide severity-based guidance.
* Added project and per-task controls to enable it, including a default
enable switch and Quick Add / Task Detail toggles.
* Enhanced advisor prompting by discovering and incorporating
`OVERSEER.md`/`WATCHDOG.md` review files.
* **Documentation**
* Added architecture and settings documentation for the new
session-advisor parity behavior.
* **Bug Fixes**
* Improved fail-soft handling so advisor behavior won’t disrupt
execution.
  * Fixed concurrent PostgreSQL migration startup failures.
* **Tests**
* Added coverage for advice parsing, emission guarding, runtime
behavior, and watchdog discovery.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-14 20:27:35 -07:00

39 lines
1.5 KiB
TypeScript

/**
* FNXC:PlannerOversight 2026-07-14-18:11:
* Session advisor (LLM overseer agent) enable inheritance mirrors GitHub tracking:
* per-task override wins, else project default, else workflow flag (backward compat),
* else off. Pure resolver — no I/O — so UI, API, and engine share one contract.
*/
import type { ProjectSettings, Task } from "./types.js";
export interface ResolvedTaskSessionAdvisor {
enabled: boolean;
source: "task" | "project" | "workflow" | "default";
}
/**
* Resolve whether the session advisor (LLM overseer agent) is enabled for a task.
*
* Precedence:
* 1. `task.sessionAdvisorEnabled` when boolean (explicit on/off for this task)
* 2. `projectSettings.sessionAdvisorEnabledByDefault` when true
* 3. Workflow `plannerOverseerAdvisorEnabled` when true (legacy / workflow-settings path)
* 4. Default false
*/
export function resolveTaskSessionAdvisorEnabled(
task: Pick<Task, "sessionAdvisorEnabled">,
projectSettings?: Pick<ProjectSettings, "sessionAdvisorEnabledByDefault">,
workflowAdvisorEnabled?: boolean,
): ResolvedTaskSessionAdvisor {
if (typeof task.sessionAdvisorEnabled === "boolean") {
return { enabled: task.sessionAdvisorEnabled, source: "task" };
}
if (projectSettings?.sessionAdvisorEnabledByDefault === true) {
return { enabled: true, source: "project" };
}
if (workflowAdvisorEnabled === true) {
return { enabled: true, source: "workflow" };
}
return { enabled: false, source: "default" };
}