feat(insights): make each person-defined symptom its own correlation channel

Every active symptom definition enters pattern discovery as an outcome
channel SYMPTOM:<id>, labelled with its decrypted name (the data label
the interpretation already prefers over the key). The daily value is the
day's highest intensity in the person's zone; days without an occurrence
count as 0 only between the first and the last logged day. At most eight,
the active-definition cap. The SYMPTOM: prefix resolves to the illness
module in the surface map, so the family leaves the matrix with the
module, and the discovery guard lists the new fetcher.
This commit is contained in:
Marc-André Bombeck committed 2026-10-03 21:14:08 +02:00
1 parent d6571c4e9c
commit 9d9e1f153c
15 files changed
+799 -4

No files matched your search

@@ -31,6 +31,7 @@ vi.mock("@/lib/db", () => ({
// channel produces a point.
environmentContext: { findMany: vi.fn().mockResolvedValue([]) },
customMetric: { findMany: vi.fn().mockResolvedValue([]) },
symptomDefinition: { findMany: vi.fn().mockResolvedValue([]) },
},
}));
@@ -153,6 +154,7 @@ beforeEach(() => {
prisma.environmentContext.findMany as ReturnType<typeof vi.fn>
).mockResolvedValue([]);
vi.mocked(prisma.customMetric.findMany).mockResolvedValue([] as never);
vi.mocked(prisma.symptomDefinition.findMany).mockResolvedValue([] as never);
});
const callGet = GET as unknown as (req: NextRequest) => Promise<Response>;
@@ -236,6 +236,7 @@ async function buildCorrelationsResponse(
// available for the scan.
environment_days: diagnostics.environmentDays,
custom_metric_channels: diagnostics.customMetricChannels,
symptom_event_channels: diagnostics.symptomEventChannels,
custom_metric_days: diagnostics.customMetricDays,
},
});