aegida-console / .superpowers / sdd / 2026-07-26-corporate-ai-chat / final-fix-report.md
final-fix-report.md
Raw

Corporate AI chat final fix report

Date: 2026-07-26

Fixed finding

The browser now enforces the same request budget as the chat route before it mutates conversation state or starts a request:

  • New messages are accepted through 32,000 characters and rejected at 32,001.
  • The composer prevents submission, retains the complete invalid draft, and exposes an accessible validation error instead of silently truncating input.
  • The hook independently rejects over-limit calls, so non-composer callers cannot create an invalid or retryable local state.
  • Completed history is reduced to the newest deterministic context suffix that fits at most 100 messages, 32,000 characters per message, and 128,000 total characters.
  • A retry is unavailable unless the immediate latest completed user message is valid and remains the tail of the sanitized request context; retrying also rechecks the current payload before transport.
  • Server validation consumes the shared limit constants, preventing client and server budgets from drifting.

TDD evidence

The focused RED run failed for the intended missing behaviors:

  • 32,001 characters still called authFetch.
  • 51 completed turns plus a new message sent 103 messages.
  • The composer exposed no over-limit error and left Send enabled.
  • The request-window module did not yet exist.
  • Persisted invalid history had no non-retryable state.
  • A native-limit paste silently truncated the draft, and a whitespace-only latest user message could be skipped to retry an older prompt.

After implementation and independent review fixes, the focused suite passed 52/52 tests. Boundary coverage includes 32,000 accepted, 32,001 rejected, exactly 100 messages, trimming above 100 messages, exactly 128,000 total characters, trimming above 128,000, and an oversized historical-message boundary.

Verification

Check Result
Focused tests Passed: 4 files, 52 tests.
npm test Passed: 11 files, 95 tests.
npm run lint Passed: exit 0.
npx tsc --noEmit Passed: exit 0.
npm run build Passed: compiled, type-checked, and generated 7/7 static pages. The first sandboxed attempt failed only because Turbopack could not bind its internal port; the approved retry outside the sandbox passed.

Residual review findings

These findings were intentionally left unchanged because they are independent of request-budget enforcement, require a separate product/interaction choice, or overlap the user's pre-existing dirty files:

  • Explicit Geist typography is absent. Restoring it affects global typography; app/globals.css already has user-owned unstaged changes.
  • The custom model menu does not dismiss on Tab/focus leave. This is a separate focus-management change and needs its own interaction tests.
  • A model selected before the first message is not persisted. This requires a new user-scoped preference/storage contract.
  • Streaming always scrolls to the bottom. A follow-mode policy needs explicit user-intent detection and dedicated scroll tests.
  • The light radial body gradient is not neutralized in dark mode. app/globals.css is user-owned and unstaged.
  • The OG card copy/model visual remains mismatched. Image generation was not called again, as explicitly prohibited.
  • The CSP test does not explicitly assert production absence of unsafe-eval. This is independent configuration-test coverage.
  • vite-tsconfig-paths remains declared but unused. package.json and package-lock.json contain user-owned unstaged changes and were not touched.

Scope protection

Only the chat request-limit implementation, its tests, and this report are staged for the final fix commit. Pre-existing changes to shadcn setup, package metadata/lockfile, utilities, and global CSS remain unstaged.