@@ -5,19 +5,20 @@ This document specifies the architecture for isolating telemetry into a separate
55## Architecture
66
77The system consists of two processes:
8+
891 . ** Main Process (Client)** : The DevTools MCP server. Spawns the Watchdog and sends raw telemetry events via IPC (Stdin).
9102 . ** Watchdog Process (Server)** : A simplified Node.js process. Manages Session IDs, enriches events, and handles the reliable transmission of ` server_shutdown ` upon detecting Main Process death.
1011
1112## Phase 1: Shared Core & Types (src/telemetry/types.ts)
1213
1314Define the IPC protocol between Master and Watchdog.
1415
15- * ** Modify** ` src/telemetry/types.ts ` :
16- * ` IpcMessageType ` enum: ` DATA = 'data' ` .
17- * ` TelemetryEvent ` interface: ` { type: IpcMessageType, payload: ChromeDevToolsMcpExtension } ` .
18- * Ensure ` ChromeDevToolsMcpExtension ` (Protobuf mapping) is exported.
19- * Add ` ServerShutdown ` interface: ` export interface ServerShutdown {} ` .
20- * Update ` ChromeDevToolsMcpExtension ` to include ` server_shutdown?: ServerShutdown ` .
16+ - ** Modify** ` src/telemetry/types.ts ` :
17+ - ` IpcMessageType ` enum: ` DATA = 'data' ` .
18+ - ` TelemetryEvent ` interface: ` { type: IpcMessageType, payload: ChromeDevToolsMcpExtension } ` .
19+ - Ensure ` ChromeDevToolsMcpExtension ` (Protobuf mapping) is exported.
20+ - Add ` ServerShutdown ` interface: ` export interface ServerShutdown {} ` .
21+ - Update ` ChromeDevToolsMcpExtension ` to include ` server_shutdown?: ServerShutdown ` .
2122
2223## Phase 2: Watchdog Process (The Sidecar)
2324
@@ -28,91 +29,100 @@ Location: `src/telemetry/watchdog/`
2829A stateful class responsible for session management and transport.
2930
3031** State:**
31- * ` #appVersion ` : string
32- * ` #osType ` : OsType
33- * ` #sessionId ` : string (Hex string)
34- * ` #sessionCreated ` : number (Timestamp)
32+
33+ - ` #appVersion ` : string
34+ - ` #osType ` : OsType
35+ - ` #sessionId ` : string (Hex string)
36+ - ` #sessionCreated ` : number (Timestamp)
3537
3638** Behavior:**
37- * ** Initialization** :
38- * Generate initial ` #sessionId ` using ` crypto.randomUUID() ` .
39- * Set ` #sessionCreated = Date.now() ` .
40- * ** ` send(event: ChromeDevToolsMcpExtension) ` ** :
41- 1 . ** Session Rotation** :
42- * Check ` Date.now() - #sessionCreated > 24 * 60 * 60 * 1000 ` (24 hours).
43- * If expired: Generate new ` #sessionId ` (UUID), reset ` #sessionCreated ` .
44- 2 . ** Enrichment** : deeply clone ` event ` . Populate:
45- * ` client_info.client_type `
46- * ` session_id ` (from state)
47- * ` app_version ` (from state)
48- * ` os_type ` (from state)
49- 3 . ** Transport** :
50- * Log the JSON stringified event using the ` logger ` from ` ../../logger.js ` .
51- * ** ` sendShutdownEvent() ` ** :
52- * Construct ` server_shutdown ` event.
53- * ** CRITICAL** : Do * not* include ` flag_usage ` (Main process might not have sent it if crashed).
54- * Calls ` this.send(shutdownEvent) ` .
39+
40+ - ** Initialization** :
41+ - Generate initial ` #sessionId ` using ` crypto.randomUUID() ` .
42+ - Set ` #sessionCreated = Date.now() ` .
43+ - ** ` send(event: ChromeDevToolsMcpExtension) ` ** :
44+ 1 . ** Session Rotation** :
45+ - Check ` Date.now() - #sessionCreated > 24 * 60 * 60 * 1000 ` (24 hours).
46+ - If expired: Generate new ` #sessionId ` (UUID), reset ` #sessionCreated ` .
47+ 2 . ** Enrichment** : deeply clone ` event ` . Populate:
48+ - ` client_info.client_type `
49+ - ` session_id ` (from state)
50+ - ` app_version ` (from state)
51+ - ` os_type ` (from state)
52+ 3 . ** Transport** :
53+ - Log the JSON stringified event using the ` logger ` from ` ../../logger.js ` .
54+ - ** ` sendShutdownEvent() ` ** :
55+ - Construct ` server_shutdown ` event.
56+ - ** CRITICAL** : Do _ not_ include ` flag_usage ` (Main process might not have sent it if crashed).
57+ - Calls ` this.send(shutdownEvent) ` .
5558
5659### 2.2 Watchdog Entry Point (` src/telemetry/watchdog/main.ts ` )
5760
5861The executable script.
5962
6063** Inputs (CLI Args):**
61- * ` --parent-pid ` : PID of the Main Process to monitor.
62- * ` --app-version ` : String.
63- * ` --os-type ` : Integer (OsType).
64- * ` --log-file ` : Absolute path for debugging logs (optional).
64+
65+ - ` --parent-pid ` : PID of the Main Process to monitor.
66+ - ` --app-version ` : String.
67+ - ` --os-type ` : Integer (OsType).
68+ - ` --log-file ` : Absolute path for debugging logs (optional).
6569
6670** Logic Flow:**
71+
67721 . ** Bootstrap** :
68- * ** Arg Parsing** : Use ` yargs ` to parse command line arguments widely.
69- * Setup internal logging (to file if ` --log-file ` provided, otherwise silent/stderr).
70- * Instantiate ` ClearcutSender ` .
73+ - ** Arg Parsing** : Use ` yargs ` to parse command line arguments widely.
74+ - Setup internal logging (to file if ` --log-file ` provided, otherwise silent/stderr).
75+ - Instantiate ` ClearcutSender ` .
71762 . ** IPC Handling (Stdin)** :
72- * ` process.stdin.resume() ` and set encoding ` utf8 ` .
73- * Stream parser (using ` readline ` or buffer splitting) for newline-delimited JSON.
74- * On valid message: ` sender.send(payload) ` .
77+ - ` process.stdin.resume() ` and set encoding ` utf8 ` .
78+ - Stream parser (using ` readline ` or buffer splitting) for newline-delimited JSON.
79+ - On valid message: ` sender.send(payload) ` .
75803 . ** Death Detection** :
76- * ** Mechanism** : Listen for ` process.stdin.on('end') ` and ` ('close') ` .
77- * ** Trigger** : On either event:
78- 1 . Log "Parent death detected".
79- 2 . ` await sender.sendShutdownEvent() ` .
80- 3 . ` process.exit(0) ` .
81+ - ** Mechanism** : Listen for ` process.stdin.on('end') ` and ` ('close') ` .
82+ - ** Trigger** : On either event:
83+ 1 . Log "Parent death detected".
84+ 2 . ` await sender.sendShutdownEvent() ` .
85+ 3 . ` process.exit(0) ` .
81864 . ** Disconnect** : Handle ` process.on('disconnect') ` similarly to death.
8287
8388## Phase 3: Main Process Client (` src/telemetry/watchdog-client.ts ` )
8489
8590Abstracts the sidecar management.
8691
8792** Class: ` WatchdogClient ` **
88- * ** Constructor** :
89- * ` parentPid ` , ` appVersion ` , ` osType ` , ` logFile ` .
90- * ** Spawning Logic** :
91- * ** Path Resolution** : Use ` import.meta.url ` to resolve the absolute path to ` watchdog/main.js ` .
92- ``` javascript
93- const watchdogPath = fileURLToPath (new URL (' ./watchdog/main.js' , import .meta.url));
94- ` ` `
95- * **Spawn**: ` child_process .spawn (process .execPath , [watchdogPath, ... dependencies])` .
96- * **Stdio Config**: ` [' pipe' , ' ignore' , ' ignore' ]` (Strictly ignore output, rely on ` -- log- file` ).
97- * **Lifecycle**: ` unref ()` the child so it doesn't block Main Process exit.
98- * **` send (message: TelemetryEvent)` **:
99- * JSON-stringify ` event ` .
100- * Append ` \n` .
101- * Write to ` child .stdin ` .
102- * Handle errors (EPIPE) gracefully (log warning, do not crash).
93+
94+ - ** Constructor** :
95+ - ` parentPid ` , ` appVersion ` , ` osType ` , ` logFile ` .
96+ - ** Spawning Logic** :
97+ - ** Path Resolution** : Use ` import.meta.url ` to resolve the absolute path to ` watchdog/main.js ` .
98+ ``` javascript
99+ const watchdogPath = fileURLToPath (
100+ new URL (' ./watchdog/main.js' , import .meta.url),
101+ );
102+ ` ` `
103+ - **Spawn**: ` child_process .spawn (process .execPath , [watchdogPath, ... dependencies])` .
104+ - **Stdio Config**: ` [' pipe' , ' ignore' , ' ignore' ]` (Strictly ignore output, rely on ` -- log- file` ).
105+ - **Lifecycle**: ` unref ()` the child so it doesn't block Main Process exit.
106+ - **` send (message: TelemetryEvent)` **:
107+ - JSON-stringify ` event ` .
108+ - Append ` \n` .
109+ - Write to ` child .stdin ` .
110+ - Handle errors (EPIPE) gracefully (log warning, do not crash).
103111
104112## Phase 4: Integration & Testing
105113
106114### 4.1 Refactor ` ClearcutLogger`
107- * Remove direct ` ClearcutSender` usage.
108- * Instantiate ` WatchdogClient` in constructor.
109- * Proxy methods (` logToolInvocation` , etc.) to ` client .send ()` .
115+
116+ - Remove direct ` ClearcutSender` usage.
117+ - Instantiate ` WatchdogClient` in constructor.
118+ - Proxy methods (` logToolInvocation` , etc.) to ` client .send ()` .
110119
111120### 4.2 Verification Plan
121+
1121221. **Unit Tests**:
113- * ` clearcut- sender .test .ts ` : Verify enrichment and session rotation logic mocking Date.
123+ - ` clearcut- sender .test .ts ` : Verify enrichment and session rotation logic mocking Date.
1141242. **Integration Tests (` spawn- kill- verify` )**:
115- * Script: Spawn Main Process (mock).
116- * Main Process spawns Watchdog.
117- * Main Process kills itself (` kill - 9 ` ).
118- * **Assert**: Watchdog writes ` server_shutdown` to log/transport before exiting.
125+ - Script: Spawn Main Process (mock).
126+ - Main Process spawns Watchdog.
127+ - Main Process kills itself (` kill - 9 ` ).
128+ - **Assert**: Watchdog writes ` server_shutdown` to log/transport before exiting.
0 commit comments