mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
fix(ai): background generation cannot spend the interactive day
The automatic generators — status and reference cards, the briefing, the
arrival reaction, the nudge, document summaries and the index backfill —
reserved against the same ceiling as the chat. On the operator's account
that meant 150-330 ledger rows a day, 172 metric generations before
06:42Z, and a ceiling already spent when he opened the chat.
Every background surface now reserves through
`resolveDailyCapFor("job", chain)`: half the cost owner's ceiling, all
job surfaces together. The interactive routes keep the whole ceiling, so
a day of background work can no longer take the user's own away.
This commit is contained in:
1 parent
2c46712e13
commit
d3196ee69e
38 files changed
+151
-17
No files matched your search
@@ -35,6 +35,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
})),
|
||||
reconcileSpend: vi.fn(async () => undefined),
|
||||
resolveDailyCap: () => 200_000,
|
||||
resolveDailyCapFor: () => 200_000,
|
||||
resolveCostOwner: () => "operator" as const,
|
||||
}));
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget: vi.fn().mockResolvedValue({ allowed: true, reserved: 600 }),
|
||||
reconcileSpend: vi.fn().mockResolvedValue(undefined),
|
||||
resolveDailyCap: vi.fn(() => 100000),
|
||||
resolveDailyCapFor: vi.fn(() => 100000),
|
||||
resolveCostOwner: vi.fn(() => "operator" as const),
|
||||
}));
|
||||
vi.mock("@/lib/ai/provider-runner", () => ({
|
||||
|
||||
@@ -69,6 +69,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget: vi.fn().mockResolvedValue({ allowed: true, reserved: 1 }),
|
||||
reconcileSpend: vi.fn().mockResolvedValue(undefined),
|
||||
resolveDailyCap: vi.fn(() => 1000),
|
||||
resolveDailyCapFor: vi.fn(() => 1000),
|
||||
resolveCostOwner: vi.fn(() => "operator" as const),
|
||||
}));
|
||||
vi.mock("@/lib/documents/extract", () => ({
|
||||
|
||||
@@ -52,6 +52,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget: vi.fn().mockResolvedValue({ allowed: true, reserved: 1 }),
|
||||
reconcileSpend: vi.fn().mockResolvedValue(undefined),
|
||||
resolveDailyCap: vi.fn(() => 1000),
|
||||
resolveDailyCapFor: vi.fn(() => 1000),
|
||||
resolveCostOwner: vi.fn(() => "operator" as const),
|
||||
}));
|
||||
vi.mock("@/lib/modules/gate", () => ({
|
||||
|
||||
@@ -40,6 +40,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget: vi.fn().mockResolvedValue({ allowed: true, reserved: 1 }),
|
||||
reconcileSpend: vi.fn().mockResolvedValue(undefined),
|
||||
resolveDailyCap: vi.fn(() => 1000),
|
||||
resolveDailyCapFor: vi.fn(() => 1000),
|
||||
resolveCostOwner: vi.fn(() => "operator" as const),
|
||||
}));
|
||||
vi.mock("@/lib/modules/gate", () => ({
|
||||
|
||||
@@ -53,6 +53,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget: vi.fn().mockResolvedValue({ allowed: true, reserved: 1 }),
|
||||
reconcileSpend: vi.fn().mockResolvedValue(undefined),
|
||||
resolveDailyCap: vi.fn(() => 1000),
|
||||
resolveDailyCapFor: vi.fn(() => 1000),
|
||||
resolveCostOwner: vi.fn(() => "operator" as const),
|
||||
}));
|
||||
vi.mock("@/lib/modules/gate", () => ({
|
||||
|
||||
@@ -105,6 +105,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget,
|
||||
reconcileSpend,
|
||||
resolveDailyCap: vi.fn(() => 2_000_000),
|
||||
resolveDailyCapFor: vi.fn(() => 2_000_000),
|
||||
resolveCostOwner: vi.fn(() => "user" as const),
|
||||
}));
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget: vi.fn(async () => ({ allowed: true, reserved: 1500 })),
|
||||
reconcileSpend: vi.fn(async () => undefined),
|
||||
resolveDailyCap: vi.fn(() => 2_000_000),
|
||||
resolveDailyCapFor: vi.fn(() => 2_000_000),
|
||||
resolveCostOwner: vi.fn(() => "user" as const),
|
||||
}));
|
||||
vi.mock("@/lib/ai/coach/refusal", () => ({
|
||||
|
||||
@@ -134,6 +134,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget,
|
||||
reconcileSpend,
|
||||
resolveDailyCap: vi.fn(() => 2_000_000),
|
||||
resolveDailyCapFor: vi.fn(() => 2_000_000),
|
||||
resolveCostOwner: vi.fn(() => "user" as const),
|
||||
}));
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget,
|
||||
reconcileSpend,
|
||||
resolveDailyCap: vi.fn(() => 2_000_000),
|
||||
resolveDailyCapFor: vi.fn(() => 2_000_000),
|
||||
resolveCostOwner: vi.fn(() => "user" as const),
|
||||
}));
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget,
|
||||
reconcileSpend,
|
||||
resolveDailyCap: vi.fn(() => 2_000_000),
|
||||
resolveDailyCapFor: vi.fn(() => 2_000_000),
|
||||
resolveCostOwner: vi.fn(() => "user" as const),
|
||||
}));
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget: vi.fn(),
|
||||
reconcileSpend: vi.fn(),
|
||||
resolveDailyCap: vi.fn(() => 200_000),
|
||||
resolveDailyCapFor: vi.fn(() => 200_000),
|
||||
resolveCostOwner: vi.fn(() => "operator" as const),
|
||||
}));
|
||||
vi.mock("@/lib/ai/coach/refusal", () => ({ detectRefusal: vi.fn() }));
|
||||
|
||||
@@ -100,6 +100,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
})),
|
||||
reconcileSpend: vi.fn(),
|
||||
resolveDailyCap: vi.fn(() => 200_000),
|
||||
resolveDailyCapFor: vi.fn(() => 200_000),
|
||||
resolveCostOwner: vi.fn(() => "operator" as const),
|
||||
}));
|
||||
vi.mock("@/lib/ai/coach/refusal", () => ({ detectRefusal: vi.fn() }));
|
||||
|
||||
@@ -103,6 +103,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget: vi.fn(async () => ({ allowed: true, reserved: 1500 })),
|
||||
reconcileSpend: vi.fn(async () => undefined),
|
||||
resolveDailyCap: vi.fn(() => 2_000_000),
|
||||
resolveDailyCapFor: vi.fn(() => 2_000_000),
|
||||
resolveCostOwner: vi.fn(() => "user" as const),
|
||||
}));
|
||||
vi.mock("@/lib/ai/coach/refusal", () => ({
|
||||
|
||||
@@ -133,6 +133,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget,
|
||||
reconcileSpend,
|
||||
resolveDailyCap: vi.fn(() => 2_000_000),
|
||||
resolveDailyCapFor: vi.fn(() => 2_000_000),
|
||||
resolveCostOwner: vi.fn(() => "user" as const),
|
||||
}));
|
||||
|
||||
|
||||
@@ -177,6 +177,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget: vi.fn(async () => ({ allowed: true, reserved: 1500 })),
|
||||
reconcileSpend: vi.fn(async () => undefined),
|
||||
resolveDailyCap: vi.fn(() => 2_000_000),
|
||||
resolveDailyCapFor: vi.fn(() => 2_000_000),
|
||||
resolveCostOwner: vi.fn(() => "user" as const),
|
||||
}));
|
||||
vi.mock("@/lib/ai/coach/refusal", () => ({
|
||||
|
||||
@@ -45,6 +45,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
reserveBudget: vi.fn(),
|
||||
reconcileSpend: vi.fn().mockResolvedValue(undefined),
|
||||
resolveDailyCap: vi.fn(() => 200_000),
|
||||
resolveDailyCapFor: vi.fn(() => 200_000),
|
||||
resolveCostOwner: vi.fn(() => "operator" as const),
|
||||
}));
|
||||
vi.mock("@/lib/labs/ocr-extract", async () => {
|
||||
|
||||
@@ -44,6 +44,7 @@ vi.mock("@/lib/ai/coach/budget", () => ({
|
||||
// returns a distinctive figure so an accidental default-cap regression is
|
||||
// visible in the assertion rather than silently passing.
|
||||
resolveDailyCap: vi.fn(() => 1_234_567),
|
||||
resolveDailyCapFor: vi.fn(() => 1_234_567),
|
||||
resolveCostOwner: vi.fn(() => "user" as const),
|
||||
}));
|
||||
|
||||
|
||||
Reference in new issue
Block a user