writetrack 0.10.3 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # WriteTrack
2
2
 
3
- Detect AI-generated and pasted text through keystroke dynamics.
3
+ Capture and analyze the writing process through keystroke dynamics.
4
4
 
5
- WriteTrack analyzes _how_ text was entered, not what was written. Human typing has natural variation in timing, rhythm, and corrections. Pasted or AI-generated text arrives all at once with no behavioral fingerprint. WriteTrack captures the difference.
5
+ WriteTrack is an embeddable SDK that instruments text inputs to record _how_ text was written timing, rhythm, corrections, clipboard usage, and composition patterns. It gives platforms behavioral evidence of the writing process, not just the finished text.
6
6
 
7
7
  - **~118KB** gzipped (18KB JS + 100KB WASM)
8
8
  - **0** runtime dependencies
@@ -58,7 +58,7 @@ import { WriteTrackPlugin } from 'writetrack/prosemirror';
58
58
  import { WriteTrackModule } from 'writetrack/quill';
59
59
  import { createWriteTrackLexical } from 'writetrack/lexical';
60
60
  import { createWriteTrackSlate } from 'writetrack/slate';
61
- import { createWriteTrackTinyMCE } from 'writetrack/tinymce';
61
+ import 'writetrack/tinymce'; // registers native TinyMCE plugin
62
62
  ```
63
63
 
64
64
  ## Output Sinks
@@ -77,7 +77,7 @@ tracker
77
77
 
78
78
  ## What It Captures
79
79
 
80
- WriteTrack instruments your text inputs and records the behavioral signals behind every keystroke:
80
+ WriteTrack instruments text inputs and records the behavioral signals behind every keystroke:
81
81
 
82
82
  - **Timing intervals** — milliseconds between each keystroke
83
83
  - **Rhythm variance** — consistency or erratic cadence
@@ -86,13 +86,29 @@ WriteTrack instruments your text inputs and records the behavioral signals behin
86
86
  - **Selection events** — text selections via mouse, keyboard, or programmatic
87
87
  - **Composition events** — IME input for CJK and other non-Latin scripts
88
88
 
89
+ ## What It Produces
90
+
91
+ WASM-powered analysis returns a `SessionAnalysis` covering seven dimensions:
92
+
93
+ - **Content origin** — what proportion was typed, pasted, or autocompleted
94
+ - **Timing authenticity** — rhythm consistency, periodicity, entropy
95
+ - **Revision behavior** — corrections, navigation, undo/redo patterns
96
+ - **Session continuity** — focus changes, tab-aways, session structure
97
+ - **Physical plausibility** — impossible sequences, synthetic event markers
98
+ - **Temporal patterns** — speed over time, warmup/fatigue, burst patterns
99
+ - **Writing process** — planning, drafting, and revision phase segmentation
100
+
101
+ Each dimension produces a machine-readable indicator code and detailed metrics suitable for visualization.
102
+
89
103
  ## Use Cases
90
104
 
91
- **Education** — Flag essays that were pasted rather than composed. Give instructors behavioral context alongside content.
105
+ **Education** — Give instructors behavioral context alongside submitted work. See whether text was composed or pasted.
106
+
107
+ **Assessment** — Add a behavioral layer to written responses. Distinguish engaged composition from copy-paste submission.
92
108
 
93
- **Research** — Distinguish survey respondents who engaged thoughtfully from those who copy-pasted boilerplate.
109
+ **Compliance** — Know when form attestations were typed versus pasted.
94
110
 
95
- **Compliance** — Add a behavioral layer to form submissions. Know when attestations were typed versus pasted.
111
+ **Research** — Capture writing process data for studies on composition behavior, revision patterns, and typing fluency.
96
112
 
97
113
  ## API
98
114
 
@@ -120,29 +136,30 @@ interface WriteTrackOptions {
120
136
 
121
137
  ### Methods
122
138
 
123
- | Method | Returns | Description |
124
- | ---------------------------------- | -------------------------------- | ------------------------------------------------- |
125
- | `start()` | `void` | Begin capturing events |
126
- | `stop()` | `void` | Stop capturing and clean up |
127
- | `getData()` | `WriteTrackDataSchema` | Export full session data |
128
- | `getText()` | `string` | Current text content |
129
- | `getRawEvents()` | `KeystrokeEvent[]` | All captured keystroke events |
130
- | `getClipboardEvents()` | `ClipboardEvent[]` | Paste/copy/cut events |
131
- | `getSelectionEvents()` | `SelectionEvent[]` | Text selection events |
132
- | `getUndoRedoEvents()` | `UndoRedoEvent[]` | Undo/redo events |
133
- | `getCompositionEvents()` | `CompositionEvent[]` | IME composition events |
134
- | `getProgrammaticInsertionEvents()` | `ProgrammaticInsertionEvent[]` | Programmatic insertion events |
135
- | `getSessionDuration()` | `number` | Session duration in ms |
136
- | `getActiveTime()` | `number` | Active (visible) session time in ms |
137
- | `getKeystrokeCount()` | `number` | Total keystrokes captured |
138
- | `getAnalysis()` | `Promise<SessionAnalysis\|null>` | WASM-powered session analysis |
139
- | `getSessionReport()` | `Promise<SessionReport>` | Combined data + analysis |
140
- | `pipe(sink)` | `this` | Register an output sink |
141
- | `on(event, handler)` | `this` | Register an event listener (`tick`, `pipe:error`) |
142
- | `isLicenseValid()` | `boolean` | Whether license is valid |
143
- | `isLicenseValidated()` | `boolean` | Whether license check has completed |
144
- | `isTargetDetached()` | `boolean` | Whether the target element was removed |
145
- | `clearPersistedData()` | `Promise<void>` | Clear IndexedDB persisted session |
139
+ | Method | Returns | Description |
140
+ | ---------------------------------- | -------------------------------- | ------------------------------------------------ |
141
+ | `start()` | `void` | Begin capturing events |
142
+ | `stop()` | `void` | Stop capturing and clean up |
143
+ | `stopAndWait()` | `Promise<void>` | Stop and wait for pending IndexedDB save |
144
+ | `getData()` | `WriteTrackDataSchema` | Export full session data |
145
+ | `getText()` | `string` | Current text content |
146
+ | `getRawEvents()` | `KeystrokeEvent[]` | All captured keystroke events |
147
+ | `getClipboardEvents()` | `ClipboardEvent[]` | Paste/copy/cut events |
148
+ | `getSelectionEvents()` | `SelectionEvent[]` | Text selection events |
149
+ | `getUndoRedoEvents()` | `UndoRedoEvent[]` | Undo/redo events |
150
+ | `getCompositionEvents()` | `CompositionEvent[]` | IME composition events |
151
+ | `getProgrammaticInsertionEvents()` | `ProgrammaticInsertionEvent[]` | Programmatic insertion events |
152
+ | `getSessionDuration()` | `number` | Session duration in ms |
153
+ | `getActiveTime()` | `number` | Active (visible) session time in ms |
154
+ | `getKeystrokeCount()` | `number` | Total keystrokes captured |
155
+ | `getAnalysis()` | `Promise<SessionAnalysis\|null>` | WASM-powered session analysis |
156
+ | `getSessionReport()` | `Promise<SessionReport>` | Combined data + analysis |
157
+ | `pipe(sink)` | `this` | Register an output sink |
158
+ | `on(event, handler)` | `() => void` | Register an event listener (returns unsubscribe) |
159
+ | `isLicenseValid()` | `boolean` | Whether license is valid |
160
+ | `isLicenseValidated()` | `boolean` | Whether license check has completed |
161
+ | `isTargetDetached()` | `boolean` | Whether the target element was removed |
162
+ | `clearPersistedData()` | `Promise<void>` | Clear IndexedDB persisted session |
146
163
 
147
164
  ### Static Methods
148
165
 
@@ -171,24 +188,58 @@ const analysis = await analyzeEvents(data, {
171
188
  });
172
189
  ```
173
190
 
191
+ ### Analysis Helpers
192
+
193
+ Convenience functions for extracting commonly needed values from a `SessionAnalysis`:
194
+
195
+ | Function | Returns | Description |
196
+ | ------------------------------------- | ---------------------------------------------------------- | -------------------------------- |
197
+ | `getSessionDurationMs(analysis)` | `number` | Session duration in milliseconds |
198
+ | `getTypingSpeed(analysis)` | `{ cpm: number; wpm: number }` | Characters and words per minute |
199
+ | `getContentOriginBreakdown(analysis)` | `{ typed: number; pasted: number; autocompleted: number }` | Content origin ratios (0-1 each) |
200
+
201
+ ```typescript
202
+ import { getTypingSpeed, getContentOriginBreakdown } from 'writetrack';
203
+
204
+ const analysis = await tracker.getAnalysis();
205
+ if (analysis) {
206
+ const { wpm } = getTypingSpeed(analysis);
207
+ const { typed, pasted } = getContentOriginBreakdown(analysis);
208
+ }
209
+ ```
210
+
211
+ ### Testing Utilities
212
+
213
+ The `writetrack/testing` subpath export provides framework-agnostic factories for creating mock WriteTrack instances and `SessionAnalysis` objects in consumer tests:
214
+
215
+ ```typescript
216
+ import { createMockAnalysis, createMockTracker } from 'writetrack/testing';
217
+
218
+ const analysis = createMockAnalysis({ keydownCount: 500 });
219
+ const tracker = createMockTracker({ analysis });
220
+ ```
221
+
222
+ | Function | Returns | Description |
223
+ | -------------------------------- | ----------------- | -------------------------------------------------- |
224
+ | `createMockAnalysis(overrides?)` | `SessionAnalysis` | Complete mock analysis with deep-partial overrides |
225
+ | `createMockTracker(options?)` | `MockWriteTrack` | Mock tracker with configurable analysis and data |
226
+
174
227
  ### Exported Types
175
228
 
176
229
  Full type definitions are included in the package:
177
230
 
178
231
  **Functions:** `analyzeEvents`, `createSessionReport`, `formatIndicator`, `getHighResolutionTime`
179
232
 
180
- **Types:** `WriteTrackOptions`, `PersistedSessionInfo`, `KeystrokeEvent`, `ClipboardEvent`, `SelectionEvent`, `UndoRedoEvent`, `CompositionEvent`, `ProgrammaticInsertionEvent`, `ModifierState`, `InputSource`, `WriteTrackDataSchema`, `DataQualityMetrics`, `SessionMetadata`, `SessionAnalysis`, `SessionReport`, `IndicatorOutput`, `ContentOriginAnalysis`, `TimingAuthenticityAnalysis`, `SessionContinuityAnalysis`, `PhysicalPlausibilityAnalysis`, `RevisionBehaviorAnalysis`, `TemporalPatternsAnalysis`, `AnalyzeEventsOptions`, `WriteTrackSink`, `WebhookOptions`, `DatadogOptions`, `DatadogClient`, `SegmentOptions`, `SegmentClient`, `OpenTelemetryOptions`, `OTelTracer`, `OTelSpan`
233
+ **Types:** `WriteTrackOptions`, `PersistedSessionInfo`, `KeystrokeEvent`, `ClipboardEvent`, `SelectionEvent`, `UndoRedoEvent`, `CompositionEvent`, `ProgrammaticInsertionEvent`, `ModifierState`, `InputSource`, `WriteTrackDataSchema`, `DataQualityMetrics`, `SessionMetadata`, `SessionAnalysis`, `SessionReport`, `IndicatorOutput`, `ContentOriginAnalysis`, `TimingAuthenticityAnalysis`, `SessionContinuityAnalysis`, `PhysicalPlausibilityAnalysis`, `RevisionBehaviorAnalysis`, `TemporalPatternsAnalysis`, `WritingProcessAnalysis`, `WritingProcessSegment`, `PhaseTransition`, `WindowFeatures`, `AnalyzeEventsOptions`, `WriteTrackSink`, `WebhookOptions`, `DatadogOptions`, `DatadogClient`, `SegmentOptions`, `SegmentClient`, `OpenTelemetryOptions`, `OTelTracer`, `OTelSpan`
181
234
 
182
235
  ## Browser Support
183
236
 
184
237
  | Browser | Version |
185
238
  | ------- | ------- |
186
- | Chrome | 62+ |
187
- | Firefox | 56+ |
188
- | Safari | 14.1+ |
189
- | Edge | 79+ |
190
-
191
- All features including license verification work at these versions. License validation uses ECDSA P-256 via `crypto.subtle`, which has been supported since Chrome 37+, Firefox 34+, Safari 11+, and Edge 79+.
239
+ | Chrome | 90+ |
240
+ | Firefox | 88+ |
241
+ | Safari | 14+ |
242
+ | Edge | 90+ |
192
243
 
193
244
  ## Privacy
194
245