| name | the-ipc-contract-audit |
| description | Audit Stave multi-file contracts before or during changes. Use when a task touches provider runtime options, IPC payloads, window.api, schemas, NormalizedProviderEvent, replay payloads, or asks for a contract or sync checklist. Trigger on phrases like "ipc", "schema", "runtimeOptions", "window.api", "provider event", "๊ณ์ฝ", "์คํค๋ง", "๋๊ธฐํ ์ฒดํฌ". |
| compatible-tools | ["claude","codex"] |
| category | safety |
| test-prompts | ["runtimeOptions์ ํ๋ ์ถ๊ฐํ๋๋ฐ ์ ๋จนํ","audit the IPC chain for this new provider event","Zod schema ๋๊ธฐํ ์ฒดํฌํด์ค","window.api ๋ฐ๊ฟจ๋๋ฐ ๋ญ ๋์ณค๋์ง ํ์ธ"] |
The IPC Contract Audit
Treat schema changes as end-to-end runtime changes, not local type edits.
Required Chain
When the task changes a provider or IPC payload, inspect this full chain:
electron/providers/types.ts
src/lib/providers/provider.types.ts
src/lib/providers/schemas.ts โ Zod discriminated union for NormalizedProviderEvent
src/types/window-api.d.ts
electron/preload.ts
electron/main/ipc/schemas.ts
- producer call sites (providers, host-service, store actions)
- consumer call sites (replay, chat UI, diagnostics)
Do not assume TypeScript is enough. electron/main/ipc/schemas.ts and src/lib/providers/schemas.ts both use strict Zod โ they silently reject extra fields and silently drop unknown event variants at parseNormalizedEvent.
Event Sync Checks
When adding, renaming, or reshaping a normalized event:
- update the TypeScript union in
src/lib/providers/provider.types.ts
- update the matching Zod object in
src/lib/providers/schemas.ts (same commit โ TS and Zod diverge silently)
- update provider emitters in
electron/providers/
- update replay handlers in
src/lib/session/provider-event-replay.ts
- update diagnostics / chat rendering if the event is user-visible
Schema variable names (e.g. StaveExecutionProcessingEventSchema) must mirror the TypeScript literal for easy auditing.
Host-Service Dispatch Pitfall
electron/host-service.ts dispatches IPC requests. Async runtime functions (e.g. attachSession, createSession) must be awaited before passing their result to respond(). A bare respond(fn(...)) when fn returns a Promise becomes JSON.stringify(Promise) === "{}" โ the renderer sees an empty object with no error.
Provider CLI Environment Parity
Changes to executable lookup, runtime env, CLI launch env, or tooling status probes must respect the env-builder contract shared across both adapters. Required check files:
electron/providers/executable-path.ts
electron/providers/cli-path-env.ts
electron/providers/claude-sdk-runtime.ts
electron/providers/codex-app-server-runtime.ts
electron/providers/runtime.ts
electron/main/utils/tooling-status.ts
A passing claude auth status or codex --version probe is not sufficient โ verify the actual turn-start path too. See the-provider-runtime-symmetry for the full symmetry protocol.
Common Failure Modes
- New field added in TypeScript only โ rejected at runtime by strict Zod in
electron/main/ipc/schemas.ts.
- New normalized event added without matching Zod entry โ silently dropped by
parseNormalizedEvent.
- Event renamed on the producer but not on replay or consumer paths.
- Host-service async result passed to
respond() without await.
Symmetry Rule
If the behavior is meant to be provider-agnostic, inspect both Claude and Codex adapters. Invoke the-provider-runtime-symmetry when the change is adapter-local but the behavior should be shared.
Verification
- run
bun run typecheck after contract changes
- if provider runtime behavior changed, smoke-check both Claude and Codex paths (start a turn in each)
- if CLI env changed, verify both the probe path and the actual turn-start path
Output
Return:
- the contract group you audited
- files confirmed
- files still at risk
- verification still required