feat(FN-4360): complete Step 6 — document reliability metrics surface

Fusion-Task-Id: FN-4360
Fusion-Task-Lineage: 50e17cef-29b0-4adc-aa1c-bffdebe4b43c
This commit is contained in:
Fusion
2026-05-13 22:22:19 -07:00
committed by gsxdsm
parent 3418fbab1d
commit 7dc0276576
4 changed files with 16 additions and 6 deletions

View File

@@ -0,0 +1,5 @@
---
"@runfusion/fusion": patch
---
Add a reliability metrics surface with `GET /api/health/reliability` and a new dashboard Reliability view showing in-review failure rate, duration percentiles, and merge-attempt distribution.

View File

@@ -677,10 +677,10 @@ The test config (`vitest.config.ts`) includes `test.css: { include: [/.+/] }` so
### Lazy-Loaded Heavy Views
These 16 views are lazy-loaded via `React.lazy()` to manage bundle size:
These 17 views are lazy-loaded via `React.lazy()` to manage bundle size:
- `AgentsView`, `NodesView`, `ChatView`, `MemoryView`
- `DevServerView`, `InsightsView`, `DocumentsView`, `SkillsView`, `ResearchView`, `EvalsView`, `TodoView`, `StashRecoveryView`
- `DevServerView`, `InsightsView`, `DocumentsView`, `SkillsView`, `ResearchView`, `ReliabilityView`, `EvalsView`, `TodoView`, `StashRecoveryView`
- `SetupWizardModal`, `PluginManager`, `PiExtensionsManager`, `AgentDetailView`
They are loaded in `App.tsx` / `AppModals.tsx` / `SettingsModal.tsx` / `AgentsView.tsx` with `<Suspense fallback={null}>`.

View File

@@ -965,10 +965,13 @@ The run-audit system records every mutation performed by the engine across three
Events are tied to specific run IDs for end-to-end traceability.
**Run audit endpoint:**
**Run audit endpoints:**
- `GET /api/agents/:id/runs/:runId/audit` — Returns audit trail for a specific agent run
- Query params: `?domain=database|git|filesystem` for filtering
- Requires agent ownership or admin access
- `GET /api/health/reliability` — Aggregates rolling reliability metrics from run-audit and task activity signals.
- Query params: `?windowDays=<1..30>` (default `7`)
- Response shape: `{ windowDays, generatedAt, headline, perDay, duration, mergeAttempts }` where missing instrumentation/samples surface as `null` with a `reason` field.
---

View File

@@ -12,6 +12,7 @@ const EXPECTED_DOCUMENTED_VIEWS = new Set([
"DocumentsView",
"SkillsView",
"ResearchView",
"ReliabilityView",
"EvalsView",
"TodoView",
"StashRecoveryView",
@@ -31,6 +32,7 @@ const EXPECTED_APP_LEVEL_VIEWS = new Set([
"ChatView",
"SkillsView",
"MemoryView",
"ReliabilityView",
"DevServerView",
"TodoView",
"StashRecoveryView",
@@ -57,18 +59,18 @@ function extractAppLazyViews(appSource: string): Set<string> {
}
describe("AGENTS lazy-loaded views inventory", () => {
it("documents the App-level lazy views accurately and keeps the curated 15-view list in sync", () => {
it("documents the App-level lazy views accurately and keeps the curated 17-view list in sync", () => {
const agentsDoc = readFileSync(resolve(__dirname, "../../../../AGENTS.md"), "utf-8");
const appSource = readFileSync(resolve(__dirname, "../App.tsx"), "utf-8");
const section = extractLazyLoadedSection(agentsDoc);
const countMatch = section.match(/These\s+(\d+)\s+views\s+are lazy-loaded/);
expect(countMatch).toBeTruthy();
expect(Number(countMatch?.[1])).toBe(16);
expect(Number(countMatch?.[1])).toBe(17);
const documentedViews = extractBacktickedNamesFromBullets(section);
expect(new Set(documentedViews)).toEqual(EXPECTED_DOCUMENTED_VIEWS);
expect(documentedViews).toHaveLength(16);
expect(documentedViews).toHaveLength(17);
expect(section).toContain("`ResearchView`");
expect(section).toContain("`TodoView`");