원클릭으로
state-coherence-v4
Protocol for high-integrity state auditing, conflict detection, and sovereign state management.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Protocol for high-integrity state auditing, conflict detection, and sovereign state management.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
# Dev Cycle Protocol: CDP Shell Sovereignty (v2.5.1)
Protocol for high-density, symmetrical shorthand logging in VS Code extensions.
Protocol for local session metadata persistence in the Virgo extension.
Architectural map and development guidelines for the Virgo extension. Mandatory reference for all agent modifications.
Protocol for high-integrity conversational AI injections and sensory parity in the Virgo extension.
Governance protocol and automated scripts for packaging and publishing the Virgo MCP standalone server to the public NPM registry. Enforces safety gates and clean extraction logic.
| name | state_coherence_v4 |
| description | Protocol for high-integrity state auditing, conflict detection, and sovereign state management. |
This skill defines the authoritative procedure for auditing state variables, identifying redundancy, and ensuring sovereign state management. It is designed to prevent "Split-Brain Syndrome" in complex applications where multiple entities (Extension, Webview, Controllers) compete for control.
Follow these four phases sequentially when tasked with a "State Audit."
WebviewStore.ts, PlaybackEngine.ts).state.x = y) versus functional updates (updateState({ x: y })).PlaybackController.ts).Create a matrix to identify redundant or overlapping variables. Use the template below:
| Variable | Scope | Mutator(s) | Redundancy Link | Issue |
|---|---|---|---|---|
isPlaying | Extension | PlaybackEngine | WebviewStore.isPlaying | Split-brain risk during IPC. |
intent | Webview | PlaybackController | WebviewStore.playbackIntent | Duplicate state in Controller/Store. |
For every "Atomic Transition" (e.g., Playing to Paused, Mode A to Mode B), ask:
Apply the Sovereign Model to resolve conflicts:
Store is a Reactive View-Model. It reflects the truth but does not define it.Controller is the Sovereign Authority. It manages timers, locks, and atomic logic.Instead of time-based locks, use incremental IDs for every user action.
// Controller
this.lastIntentId = generateId();
this.store.update({ intentId: this.lastIntentId, locked: true });
// Sync Handler
if (incomingData.intentId < this.store.getIntentId()) {
return; // Discard stale packet
}
The most robust pattern for highly reactive UIs. Instead of discarding entire packets based on stale IDs, the system filters fields by their impact.
availableVoices, hasDocuments, activeFileName, snippetHistory.cacheCount, cacheSizeBytes, engineHealth, isHydrated.totalChapters, activeChapterTitle.Playback: isPlaying, isPaused, isSelectingVoice, playbackIntent, lastLoadType, isAwaitingSync, isPreviewing, isLooping, activeMode.
Position: currentChapterIndex, currentSentenceIndex, activeQueue.
Health: playbackStalled, isRefreshing, isBuffering.
Intent: playbackIntentId, batchIntentId.
Immunity Window: A shortened sovereignty window (1500ms) that allows the UI to recover faster from failed or slow synthesis.
To prevent synchronization drift during initialization, all intent-based IDs MUST follow a strict baseline:
playbackIntentId and batchIntentId MUST initialize to 1 in all environments (Extension Host, Webview Store, Engine).WebviewStore constructor and disposed state MUST use 1.UI_SYNC pulse.To close the feedback loop for automated agents, the Webview Store implements a log-based handshake:
[STORE-SYNC-COMPLETE]patchState only when a state change actually occurs (diff detection).eval-webview) or subsequent actions.state objects. All synced properties must be top-level.intentId as a session baton. Jumps/Stops mint a new ID; continuity (auto-next/pre-fetch) inherits the current ID.isSyncing) into a single method or a Controller property.patchState to implement segmented sovereignty (Filtering Disruptive vs Telemetry fields).SOVEREIGNTY_WINDOW is tuned (e.g. 1500ms) for high-performance synthesis.null vs undefined at API Boundaries (observed: 2026-04-10)Problem: Internal service state fields (e.g., SyncManager._pendingSnippetHistory) legitimately use null to represent "no data yet loaded" — a meaningful sentinel distinct from undefined. However, API call sites (e.g., DashboardRelay.sync()) accept SnippetHistory | undefined, NOT null. Passing null directly produces a TypeScript type error and may cause unexpected runtime behavior in callers that check if (data) vs if (data !== undefined).
Law: Internal service state fields that can be absent MUST use T | null. At every API call site crossing a module boundary, null MUST be coerced to undefined using the null-coalescing operator:
// REQUIRED pattern — SyncManager.ts calling DashboardRelay.sync()
this._dashboardRelay.sync(historyToSync ?? undefined, this._activeSessionId);
// ^^^^^^^^^
// null stays internal; undefined crosses the API boundary
Rule: Never widen an internal field to T | null | undefined just to match a call site. Keep types precise internally; coerce at the boundary.
Test Expectation Corollary: When the internal field value is null at flush time (no history loaded), the spy expectation MUST assert undefined, not null:
// CORRECT — matches the null→undefined coercion at the boundary:
expect(mockDashboardRelay.sync).toHaveBeenCalledWith(undefined, 'SESSION-ID');
// WRONG — null never crosses the boundary:
expect(mockDashboardRelay.sync).toHaveBeenCalledWith(null, 'SESSION-ID');
---
## 6. Argument-Aware Engine Consistency 🧪
To ensure 100% test reliability and prevent race conditions between local logic and asynchronous `Store` synchronization, engine components MUST prioritize explicit arguments over store state in internal methods.
### 6.1 The Shadow Argument Pattern
When an engine method (e.g., `setRate`) is called, it should pass its value to a private worker method that accepts an optional parameter. The worker should only fall back to the store if the parameter is missing.
```typescript
// WebviewAudioEngine.ts
public setRate(val: number): void {
this._applyPlaybackRate(val); // Explicitly pass the value
}
private _applyPlaybackRate(requestedRate?: number): void {
const state = WebviewStore.getInstance().getState();
const rate = requestedRate ?? state.rate; // Priority: Argument > Store
// ... apply rate
}
Rationale: