617 lines
19 KiB
Markdown
617 lines
19 KiB
Markdown
# Pre-deployment Fix Wave Report
|
||
|
||
Date: 2026-07-14
|
||
Worktree: `/home/chirone/ThothII/.worktrees/activity-log-cte-layout`
|
||
Base: `e5366d14a6da8fb331d94be60b8929cefb1fe3e0`
|
||
|
||
## Outcome
|
||
|
||
All three reviewed findings are implemented in one coherent backend/frontend wave:
|
||
|
||
1. Resume leaves the prior selection, Zustand state, document panel, and EventSource untouched
|
||
until `POST /resume` succeeds. Cold Resume changes state and reconnects only after backend
|
||
clear/rebind; already-active same-session Resume preserves the existing binding; failure is a
|
||
no-op apart from the fixed toast.
|
||
2. SSE uses monotonically increasing per-session ids, cursor-filtered replay, native and manual
|
||
reconnect cursors, id continuity across `hub.clear`, and descriptor-id pending-gate
|
||
idempotence at both backend and frontend layers.
|
||
3. Generic Pi system events and readiness errors are projected through explicit public
|
||
allowlists. Sentinel URLs, paths, tokens, stderr, commands, and extra fields do not reach HTTP
|
||
or SSE.
|
||
|
||
No harness, workflow, persistence, model, CTE viewer, CTE card, or shared Card file changed.
|
||
|
||
## Interfaces
|
||
|
||
- Frontend `resumeSession(id)` now returns
|
||
`Promise<{ id: string; alreadyActive: boolean }>` via `ResumeSessionResult`.
|
||
- Backend successful Resume always returns the same shape:
|
||
- running/waiting runtime: `{ id, alreadyActive: true }`
|
||
- validated cold runtime: `{ id, alreadyActive: false }`
|
||
- `SseHub.publish(sessionId, event, data): number` returns the assigned SSE id.
|
||
- `SseHub.subscribe(sessionId, send, { afterId, pending })` calls
|
||
`send(event, data, id)` for replay/live frames with `id > afterId`.
|
||
- `GET /sessions/:id/events` accepts native `Last-Event-ID` and manual
|
||
`?lastEventId=<integer>`; when both are valid it uses the greater cursor.
|
||
- Every emitted SSE frame is `id: <n>\nevent: <name>\ndata: <json>\n\n`.
|
||
- Public readiness failure is exactly:
|
||
`Session services are not ready. Check configuration and connectivity, then try again.`
|
||
- Generic Pi system events are exactly `{ type: "system_event", event }`, and `event` must be a
|
||
non-empty string.
|
||
|
||
## Files
|
||
|
||
Backend production:
|
||
|
||
- `backend/src/bridge/session-bridge.ts`
|
||
- `backend/src/routes/sessions.ts`
|
||
- `backend/src/sse/sse-hub.ts`
|
||
|
||
Backend tests:
|
||
|
||
- `backend/test/routes-sessions.test.ts`
|
||
- `backend/test/session-bridge.test.ts`
|
||
- `backend/test/sse-hub.test.ts`
|
||
- `backend/test/sse-route.test.ts` (new)
|
||
|
||
Frontend production/support:
|
||
|
||
- `frontend/src/api/sessions.ts`
|
||
- `frontend/src/api/types.ts`
|
||
- `frontend/src/shell/AppShell.tsx`
|
||
- `frontend/src/store/sessionStore.ts`
|
||
- `frontend/src/stream/useSessionStream.ts`
|
||
- `frontend/src/test/fakeEventSource.ts`
|
||
|
||
Frontend tests:
|
||
|
||
- `frontend/src/api/sessions.test.ts`
|
||
- `frontend/src/shell/AppShell.session-mgmt.test.tsx`
|
||
- `frontend/src/store/sessionStore.test.ts`
|
||
- `frontend/src/stream/useSessionStream.test.tsx`
|
||
|
||
## TDD RED/GREEN evidence
|
||
|
||
### 1. Backend Resume result and client-boundary allowlists
|
||
|
||
RED command:
|
||
|
||
```text
|
||
cd backend && npx vitest run test/routes-sessions.test.ts test/session-bridge.test.ts
|
||
```
|
||
|
||
RED output (exit 1):
|
||
|
||
```text
|
||
Test Files 2 failed (2)
|
||
Tests 6 failed | 35 passed (41)
|
||
|
||
expected { id: 's1' } to deeply equal { id: 's1', alreadyActive: false }
|
||
expected raw readiness URL/token/path to equal the fixed public message
|
||
expected three raw generic system events to equal [{ type: 'system_event', event: 'session_exit' }]
|
||
```
|
||
|
||
GREEN command:
|
||
|
||
```text
|
||
cd backend && npx vitest run test/routes-sessions.test.ts test/session-bridge.test.ts
|
||
```
|
||
|
||
GREEN output (exit 0):
|
||
|
||
```text
|
||
✓ test/session-bridge.test.ts (14 tests)
|
||
✓ test/routes-sessions.test.ts (27 tests)
|
||
Test Files 2 passed (2)
|
||
Tests 41 passed (41)
|
||
```
|
||
|
||
### 2. Backend exact-once SseHub and route framing
|
||
|
||
RED command:
|
||
|
||
```text
|
||
cd backend && npx vitest run test/sse-hub.test.ts test/sse-route.test.ts
|
||
```
|
||
|
||
RED output (exit 1):
|
||
|
||
```text
|
||
Test Files 2 failed (2)
|
||
Tests 7 failed (7)
|
||
|
||
expected [undefined, undefined, undefined] to deeply equal [1, 2, 3]
|
||
expected unconditional replay not to contain "one" / "two"
|
||
expected one buffered pending gate, received replay plus a second pending emission
|
||
```
|
||
|
||
GREEN command:
|
||
|
||
```text
|
||
cd backend && npx vitest run test/sse-hub.test.ts test/sse-route.test.ts
|
||
```
|
||
|
||
GREEN output (exit 0):
|
||
|
||
```text
|
||
✓ test/sse-hub.test.ts (4 tests)
|
||
✓ test/sse-route.test.ts (3 tests)
|
||
Test Files 2 passed (2)
|
||
Tests 7 passed (7)
|
||
```
|
||
|
||
### 3. Frontend cursor tracking and gate idempotence
|
||
|
||
RED command:
|
||
|
||
```text
|
||
cd frontend && npx vitest run src/stream/useSessionStream.test.tsx src/store/sessionStore.test.ts
|
||
```
|
||
|
||
RED output (exit 1):
|
||
|
||
```text
|
||
Test Files 2 failed (2)
|
||
Tests 2 failed | 28 passed (30)
|
||
|
||
expected /sessions/s1/events to be /sessions/s1/events?lastEventId=7
|
||
expected duplicate gate pendingWidget to remain null, received gate-1
|
||
```
|
||
|
||
GREEN command:
|
||
|
||
```text
|
||
cd frontend && npx vitest run src/stream/useSessionStream.test.tsx src/store/sessionStore.test.ts
|
||
```
|
||
|
||
GREEN output (exit 0):
|
||
|
||
```text
|
||
✓ src/store/sessionStore.test.ts (23 tests)
|
||
✓ src/stream/useSessionStream.test.tsx (7 tests)
|
||
Test Files 2 passed (2)
|
||
Tests 30 passed (30)
|
||
```
|
||
|
||
### 4. Frontend typed Resume and AppShell ordering/preservation
|
||
|
||
Typed API RED command:
|
||
|
||
```text
|
||
cd frontend && npx tsc -b
|
||
```
|
||
|
||
Typed API RED output (exit 1):
|
||
|
||
```text
|
||
src/api/sessions.test.ts(43,9): error TS2322: Type 'void' is not assignable to type
|
||
'{ id: string; alreadyActive: boolean; }'.
|
||
```
|
||
|
||
Lifecycle RED command:
|
||
|
||
```text
|
||
cd frontend && npx vitest run src/api/sessions.test.ts src/shell/AppShell.session-mgmt.test.tsx
|
||
```
|
||
|
||
Lifecycle RED output (exit 1):
|
||
|
||
```text
|
||
✓ src/api/sessions.test.ts (9 tests)
|
||
❯ src/shell/AppShell.session-mgmt.test.tsx (15 tests | 4 failed)
|
||
Test Files 1 failed | 1 passed (2)
|
||
Tests 4 failed | 20 passed (24)
|
||
|
||
already-active same-session Resume created two EventSources instead of one
|
||
deferred cold Resume closed the document panel before POST completion
|
||
failed same-session Resume closed the prior EventSource
|
||
failed Resume with no active session opened an EventSource
|
||
```
|
||
|
||
GREEN commands:
|
||
|
||
```text
|
||
cd frontend && npx vitest run src/api/sessions.test.ts src/shell/AppShell.session-mgmt.test.tsx
|
||
cd frontend && npx tsc -b
|
||
```
|
||
|
||
GREEN output (exit 0):
|
||
|
||
```text
|
||
✓ src/api/sessions.test.ts (9 tests)
|
||
✓ src/shell/AppShell.session-mgmt.test.tsx (15 tests)
|
||
Test Files 2 passed (2)
|
||
Tests 24 passed (24)
|
||
TypeScript: no output, exit 0
|
||
```
|
||
|
||
The AppShell cold-reconnect test additionally proves that the old source accepts an event while
|
||
Resume is pending, the replacement URL carries `lastEventId=8`, the replacement receives one
|
||
post-resume transcript/activity row, and two deliveries of the same descriptor id yield one gate.
|
||
|
||
## Affected verification
|
||
|
||
Backend command:
|
||
|
||
```text
|
||
cd backend && npx vitest run test/routes-sessions.test.ts test/session-bridge.test.ts \
|
||
test/sse-hub.test.ts test/sse-route.test.ts test/health.test.ts test/e2e-f1.test.ts
|
||
```
|
||
|
||
Output (exit 0):
|
||
|
||
```text
|
||
Test Files 6 passed (6)
|
||
Tests 52 passed (52)
|
||
```
|
||
|
||
Backend typecheck:
|
||
|
||
```text
|
||
cd backend && npx tsc --noEmit -p .
|
||
```
|
||
|
||
Output: no output, exit 0.
|
||
|
||
Frontend command:
|
||
|
||
```text
|
||
cd frontend && npx vitest run src/api/sessions.test.ts src/store/sessionStore.test.ts \
|
||
src/stream/useSessionStream.test.tsx src/shell/AppShell.session-mgmt.test.tsx \
|
||
src/shell/CentralStatus.test.tsx src/shell/ModelActivityPanel.test.tsx \
|
||
src/shell/f1-loop.test.tsx src/shell/AppShell.new-session.test.tsx
|
||
```
|
||
|
||
Output (exit 0):
|
||
|
||
```text
|
||
Test Files 8 passed (8)
|
||
Tests 74 passed (74)
|
||
```
|
||
|
||
Frontend typecheck:
|
||
|
||
```text
|
||
cd frontend && npx tsc -b
|
||
```
|
||
|
||
Output: no output, exit 0.
|
||
|
||
## Full verification
|
||
|
||
Backend full suite:
|
||
|
||
```text
|
||
cd backend && npx vitest run
|
||
```
|
||
|
||
```text
|
||
Test Files 22 passed (22)
|
||
Tests 177 passed (177)
|
||
```
|
||
|
||
Frontend full suite:
|
||
|
||
```text
|
||
cd frontend && npx vitest run
|
||
```
|
||
|
||
```text
|
||
Test Files 43 passed (43)
|
||
Tests 271 passed (271)
|
||
```
|
||
|
||
Backend production build:
|
||
|
||
```text
|
||
cd backend && npm run build
|
||
> tsc -p tsconfig.json
|
||
exit 0
|
||
```
|
||
|
||
Frontend production build:
|
||
|
||
```text
|
||
cd frontend && npm run build
|
||
> tsc -b && vite build
|
||
✓ 4835 modules transformed.
|
||
✓ built in 8.25s
|
||
exit 0
|
||
```
|
||
|
||
## Integrated re-review closure (2026-07-15)
|
||
|
||
This section supersedes the earlier cold same-session assertion that the replacement URL carries
|
||
`lastEventId=8`. That behavior was correct only while the backend process and its in-memory id
|
||
sequence survived. A restarted backend begins a fresh sequence, so a successful cold Resume now
|
||
explicitly discards the browser's cursor before replacing the EventSource.
|
||
|
||
All four integrated re-review findings are closed:
|
||
|
||
1. `AppShell` passes a dedicated cursor-reset epoch to `useSessionStream`. A cold same-session
|
||
Resume increments it only after `alreadyActive: false`; a high cursor such as `901` is omitted
|
||
from the replacement URL and fresh low-id events/gates are consumed. An already-active
|
||
same-session Resume still preserves its source, cursor, and store.
|
||
2. `useSessionStream` no longer mutates the cursor ref during render. Effect setup resets cursor
|
||
state on session/reset-epoch changes, callbacks are guarded by a captured active-source
|
||
identity, and cleanup clears only its own active identity. A queued event from the replaced
|
||
source cannot write the new store or poison its next reconnect URL.
|
||
3. Backend Resume is serialized per session and rechecks runtime state inside the lock. Manifest,
|
||
readiness, and reopen validation precede the transport commit. Idle/failed replacement creates
|
||
and binds the new runtime before `hub.clear`, which occurs synchronously immediately before the
|
||
first `Resuming session` publish. Reopen/create failure returns exactly
|
||
`Session could not be resumed. Check configuration and connectivity, then try again.`, keeps the
|
||
prior hub buffer/subscribers attached, and does not expose exception sentinels. Concurrent calls
|
||
perform one cold start and the waiter returns `alreadyActive: true`.
|
||
4. `SseHub.forget(id)` removes subscribers, buffered events, and the last id. Permanent session
|
||
DELETE invokes it after disk deletion; ordinary close and Resume continue to use `clear`, which
|
||
preserves the id sequence.
|
||
|
||
### Re-review files
|
||
|
||
Production:
|
||
|
||
- `backend/src/pi/pi-process-manager.ts`
|
||
- `backend/src/routes/sessions.ts`
|
||
- `backend/src/sse/sse-hub.ts`
|
||
- `frontend/src/shell/AppShell.tsx`
|
||
- `frontend/src/stream/useSessionStream.ts`
|
||
|
||
Tests/support:
|
||
|
||
- `backend/test/pi-process-manager.test.ts`
|
||
- `backend/test/routes-sessions.test.ts`
|
||
- `backend/test/sse-hub.test.ts`
|
||
- `frontend/src/shell/AppShell.session-mgmt.test.tsx`
|
||
- `frontend/src/stream/useSessionStream.test.tsx`
|
||
- `frontend/src/test/fakeEventSource.ts`
|
||
|
||
### Re-review TDD RED/GREEN evidence
|
||
|
||
Frontend RED command:
|
||
|
||
```text
|
||
cd frontend && npx vitest run src/stream/useSessionStream.test.tsx \
|
||
src/shell/AppShell.session-mgmt.test.tsx
|
||
```
|
||
|
||
RED output (exit 1):
|
||
|
||
```text
|
||
Test Files 2 failed (2)
|
||
Tests 3 failed | 21 passed (24)
|
||
|
||
reset epoch: expected the old source to close, received false
|
||
cold same-session: expected /sessions/s1/events, received ?lastEventId=901
|
||
stale source: expected an empty transcript, received "stale session one"
|
||
```
|
||
|
||
Frontend GREEN command:
|
||
|
||
```text
|
||
cd frontend && npx vitest run src/stream/useSessionStream.test.tsx \
|
||
src/shell/AppShell.session-mgmt.test.tsx
|
||
cd frontend && npx tsc -b
|
||
```
|
||
|
||
GREEN output (exit 0):
|
||
|
||
```text
|
||
Test Files 2 passed (2)
|
||
Tests 24 passed (24)
|
||
TypeScript: no output, exit 0
|
||
```
|
||
|
||
Backend RED command:
|
||
|
||
```text
|
||
cd backend && npx vitest run test/sse-hub.test.ts test/routes-sessions.test.ts
|
||
```
|
||
|
||
RED output (exit 1):
|
||
|
||
```text
|
||
Test Files 2 failed (2)
|
||
Tests 8 failed | 28 passed (36)
|
||
|
||
three Resume ordering assertions observed clear before reopen/create
|
||
reopen and create sentinels escaped as raw HTTP 500 responses
|
||
the concurrent waiter cold-started again instead of returning alreadyActive: true
|
||
SseHub.forget was absent and DELETE did not invoke permanent cleanup
|
||
```
|
||
|
||
Backend GREEN command:
|
||
|
||
```text
|
||
cd backend && npx vitest run test/sse-hub.test.ts test/routes-sessions.test.ts
|
||
cd backend && npx tsc --noEmit -p .
|
||
```
|
||
|
||
GREEN output (exit 0):
|
||
|
||
```text
|
||
Test Files 2 passed (2)
|
||
Tests 36 passed (36)
|
||
TypeScript: no output, exit 0
|
||
```
|
||
|
||
The failure tests publish a post-failure probe through the same hub and prove that a subscriber
|
||
attached before either reopen or create rejection still receives it. The concurrency test overlaps
|
||
two same-id requests behind a deferred reopen and proves one manifest/readiness/reopen/create/clear
|
||
sequence.
|
||
|
||
### Initial re-review verification (before independent-review hardening)
|
||
|
||
```text
|
||
cd backend && npx vitest run
|
||
Test Files 22 passed (22)
|
||
Tests 182 passed (182)
|
||
|
||
cd frontend && npx vitest run
|
||
Test Files 43 passed (43)
|
||
Tests 273 passed (273)
|
||
|
||
cd backend && npm run build
|
||
> tsc -p tsconfig.json
|
||
exit 0
|
||
|
||
cd frontend && npm run build
|
||
> tsc -b && vite build
|
||
✓ 4835 modules transformed.
|
||
✓ built in 8.46s
|
||
exit 0
|
||
```
|
||
|
||
`git diff --check` produced no output (exit 0). The frontend build retains its pre-existing
|
||
large-chunk warning; no new build or type errors were introduced.
|
||
|
||
Final whitespace verification:
|
||
|
||
```text
|
||
git diff --check
|
||
no output, exit 0
|
||
```
|
||
|
||
## Self-review
|
||
|
||
- Resume sequencing: reopen and runtime binding precede backend `clear` and HTTP success; frontend
|
||
state mutation and cursor-reset epoch follow it. Failure catch only emits fixed UI copy.
|
||
- Already active: same-session returns before reset/generation/manifest repaint; different session
|
||
resets the single-session store and binds the new id only after success.
|
||
- SSE exact-once: ids are transport identity, not content hashes; replay is strictly `id > cursor`;
|
||
`clear` retains the counter; pending gate matching uses only descriptor id.
|
||
- Cursor behavior: hook tracks `MessageEvent.lastEventId`, carries it only to an ordinary same-id
|
||
generation, and resets it on session-id/cold-runtime epoch change. Native EventSource reconnect
|
||
remains supported by the route header.
|
||
- Gate defense: the Zustand set survives pending clear but resets with the session store.
|
||
- Client boundary: raw `ensure.error` is unused in public responses; generic Pi system events are
|
||
reconstructed rather than spread; frontend type mirrors the two-field event.
|
||
- Scope: `git diff` contains no CTE/Card/harness/workflow/persistence/model changes. Four pre-existing
|
||
modified `.superpowers/sdd/{progress,task-2-report,task-3-report,task-4-report}.md` files are user
|
||
work and are excluded from staging.
|
||
|
||
## Remaining concerns
|
||
|
||
- The 200-event SSE ring limit remains intentional. A brand-new page can reconstruct only retained
|
||
backlog; an in-memory same-session reconnect is exact-once from its cursor.
|
||
- Per-session sequence counters remain in backend memory after `clear` by design so later in-process
|
||
cold same-id Resume cannot reuse ids. Permanent DELETE removes the counter via `forget`.
|
||
- Frontend tests still print pre-existing MSW unhandled-request and React ref/`act` warnings even
|
||
though all 276 tests pass. The frontend production build still reports pre-existing large chunk
|
||
warnings. Neither warning class was introduced or expanded by this change.
|
||
- No live Pi/DWH smoke was run; this wave changes only REST/SSE/frontend lifecycle boundaries and
|
||
is covered by fake-Pi, live Fastify SSE, component, full-suite, typecheck, and production-build
|
||
gates.
|
||
|
||
## Independent-review hardening
|
||
|
||
The required independent review was run repeatedly against the uncommitted diff. Its first pass
|
||
found four Important lifecycle edges beyond the integrated findings: queued old-runtime callbacks,
|
||
post-spawn construction cleanup, concurrent frontend Resume completions, and the passive-effect
|
||
commit window. Its second pass confirmed those fixes and identified one remaining Important
|
||
retention issue in the new runtime-identity map. The final pass reported no Critical, Important, or
|
||
Minor findings and assessed the diff ready to merge.
|
||
|
||
The resulting hardening is:
|
||
|
||
- Runtime bridge callbacks are gated by the bound runtime identity. Replacement, close, and DELETE
|
||
invalidate the old identity, so queued old events cannot publish or call `failSession`. An active
|
||
runtime removed by the manager can still publish its complete public failure sequence; after the
|
||
terminal unmanaged `agent_end`, its binding is released and later events are rejected.
|
||
- `PiProcessManager` kills the spawned child and removes any registered map entry if either
|
||
spawn-boundary stderr setup or later RPC/bridge/map initialization throws.
|
||
- Resume completion compares against synchronously maintained current active-session identity.
|
||
Concurrent `alreadyActive: false` then `alreadyActive: true` results preserve the cold source,
|
||
cursor, store, and replayed gate.
|
||
- Stream source replacement uses a layout effect. A deterministic later-layout-effect test delivers
|
||
a queued old event inside the former commit-to-passive-cleanup window and proves it is ignored.
|
||
- Cursor tests cover both a restarted backend's fresh low ids and an in-process hub's preserved high
|
||
ids followed by a cursor-bearing ordinary reconnect.
|
||
|
||
### Hardening TDD RED/GREEN evidence
|
||
|
||
Backend identity/construction RED command:
|
||
|
||
```text
|
||
cd backend && npx vitest run test/pi-process-manager.test.ts test/routes-sessions.test.ts
|
||
```
|
||
|
||
```text
|
||
Test Files 2 failed (2)
|
||
Tests 3 failed | 69 passed (72)
|
||
|
||
post-spawn reader initialization did not kill the child
|
||
replaced and deleted runtime callbacks still called failSession/published
|
||
```
|
||
|
||
Additional spawn-boundary and terminal-release RED checks:
|
||
|
||
```text
|
||
cd backend && npx vitest run test/pi-process-manager.test.ts \
|
||
-t "spawn boundary initialization"
|
||
Tests 1 failed | 38 skipped (39)
|
||
|
||
cd backend && npx vitest run test/routes-sessions.test.ts -t "terminal sequence"
|
||
Tests 1 failed | 34 skipped (35)
|
||
```
|
||
|
||
Frontend concurrency/layout RED command:
|
||
|
||
```text
|
||
cd frontend && npx vitest run src/stream/useSessionStream.test.tsx \
|
||
src/shell/AppShell.session-mgmt.test.tsx
|
||
```
|
||
|
||
```text
|
||
Test Files 2 failed (2)
|
||
Tests 2 failed | 25 passed (27)
|
||
|
||
the later-layout-effect event wrote "commit-window stale text"
|
||
the false→true completion pair erased pending gate "cold-gate"
|
||
```
|
||
|
||
Final focused GREEN commands:
|
||
|
||
```text
|
||
cd backend && npx vitest run test/pi-process-manager.test.ts \
|
||
test/routes-sessions.test.ts test/sse-hub.test.ts
|
||
cd backend && npx tsc --noEmit -p .
|
||
|
||
Test Files 3 passed (3)
|
||
Tests 79 passed (79)
|
||
TypeScript: no output, exit 0
|
||
|
||
cd frontend && npx vitest run src/stream/useSessionStream.test.tsx \
|
||
src/shell/AppShell.session-mgmt.test.tsx
|
||
cd frontend && npx tsc -b
|
||
|
||
Test Files 2 passed (2)
|
||
Tests 27 passed (27)
|
||
TypeScript: no output, exit 0
|
||
```
|
||
|
||
### Final full verification after review hardening
|
||
|
||
```text
|
||
cd backend && npx vitest run
|
||
Test Files 22 passed (22)
|
||
Tests 188 passed (188)
|
||
|
||
cd frontend && npx vitest run
|
||
Test Files 43 passed (43)
|
||
Tests 276 passed (276)
|
||
|
||
cd backend && npm run build
|
||
> tsc -p tsconfig.json
|
||
exit 0
|
||
|
||
cd frontend && npm run build
|
||
> tsc -b && vite build
|
||
✓ 4835 modules transformed.
|
||
✓ built in 8.47s
|
||
exit 0
|
||
```
|
||
|
||
The final frontend run retains the repository's pre-existing MSW/ref/`act` warnings, and the build
|
||
retains the pre-existing large-chunk warning. No test, typecheck, or build failures remain.
|