## Summary Engine and dashboard traffic now stays on the authoritative PostgreSQL layer across execution, recovery, project discovery, planning sessions, analytics, and shutdown. The dashboard no longer presents a migration notice for a cutover that is already mandatory. ## Design decisions - Runtime composition requires an async data layer instead of constructing a hidden SQLite fallback. - Engine workflow, mission, claim, and self-healing reads await their PostgreSQL-backed store contracts. - Project-scoped dashboard stores retain and close their backend owner exactly once. - The dashboard test quarantine entry remains paired with its Vitest exclusion, preserving the repository’s deletion-ratchet policy. ## Validation - Core, Engine, Dashboard, CLI, and Desktop typechecks pass on the stacked branch. - `pnpm test:gate` passes all 478 gate tests. - This PR changes 62 files. ## Stack - Depends on #2108. - CLI/desktop/ops, plugins, and docs/release follow in later PRs. Related: #2105 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Project discovery now recognizes projects using the `.fusion/project.json` marker. * Knowledge indexing and search are more reliable across project-scoped storage. * **Bug Fixes** * Improved session, audit timeline, approval, monitoring, and analytics data consistency. * Prevented stale planning-session updates and project-store shutdown races. * Ensured chat usage and CLI session status are saved before continuing. * **UI Changes** * Removed the storage migration notice banner now that the PostgreSQL transition is complete. * **Reliability** * Improved shutdown handling, workflow execution, and worktree behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
/**
|
|
* Engine-side helper: merge per-task EFFECTIVE workflow settings (U3, KTD-3) over a
|
|
* base settings object fetched from the store, so the engine's flat
|
|
* `settings.<key>` read sites pick up workflow-setting values with zero changes at
|
|
* the read sites.
|
|
*
|
|
* TWO-TIER MERGE (the parity-preserving rule):
|
|
* - a STORED workflow value ALWAYS overrides the base (the workflow tuned it);
|
|
* - a declaration-DEFAULT-only key (no stored value) only FILLS the base when the
|
|
* base lacks the key.
|
|
*
|
|
* This is what keeps U3 behavior-identical BEFORE the U4 hard-move: a customized
|
|
* project setting still present in the base is NOT clobbered by a declaration
|
|
* default; only a real stored workflow value overrides it. After the hard-move the
|
|
* base lacks the moved key, so the declaration default fills it. Absent-default
|
|
* model lanes contribute nothing, so they never override a real project value.
|
|
*
|
|
* `resolveEffectiveSettingsDetailed` never throws (degrades to declaration
|
|
* defaults), so this helper is a thin store-coupled wrapper that also never throws.
|
|
*/
|
|
|
|
import {
|
|
applyWorkflowSettingsOverlay,
|
|
resolveEffectiveSettingsDetailed,
|
|
type Settings,
|
|
type TaskStore,
|
|
} from "@fusion/core";
|
|
|
|
/** The minimal task shape the resolver needs. Task carries no projectId field —
|
|
* the project key is derived from the store. */
|
|
export interface EffectiveSettingsTask {
|
|
id: string;
|
|
}
|
|
|
|
/**
|
|
* Merge `base` with the task's effective workflow settings via the two-tier rule
|
|
* (stored overrides; default-only fills only-absent). Returns a NEW object; `base`
|
|
* is not mutated. Degrades to returning `base` unchanged on any resolver error.
|
|
*/
|
|
export async function mergeEffectiveSettings<T extends Partial<Settings>>(
|
|
store: Pick<
|
|
TaskStore,
|
|
| "getTaskWorkflowSelection"
|
|
| "getTaskWorkflowSelectionAsync"
|
|
| "getWorkflowDefinition"
|
|
| "getWorkflowSettingValues"
|
|
| "getWorkflowSettingsProjectId"
|
|
>,
|
|
task: EffectiveSettingsTask,
|
|
base: T,
|
|
): Promise<T> {
|
|
try {
|
|
const detailed = await resolveEffectiveSettingsDetailed(
|
|
store as Parameters<typeof resolveEffectiveSettingsDetailed>[0],
|
|
task,
|
|
);
|
|
return applyWorkflowSettingsOverlay(base, detailed);
|
|
} catch {
|
|
return base;
|
|
}
|
|
}
|