claude-code-workflow 6.3.22 → 6.3.24

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.
Files changed (42) hide show
  1. package/.claude/agents/issue-plan-agent.md +10 -5
  2. package/.claude/commands/issue/plan.md +1 -1
  3. package/.claude/skills/review-code/SKILL.md +170 -0
  4. package/.claude/skills/review-code/phases/actions/action-collect-context.md +139 -0
  5. package/.claude/skills/review-code/phases/actions/action-complete.md +115 -0
  6. package/.claude/skills/review-code/phases/actions/action-deep-review.md +302 -0
  7. package/.claude/skills/review-code/phases/actions/action-generate-report.md +263 -0
  8. package/.claude/skills/review-code/phases/actions/action-quick-scan.md +164 -0
  9. package/.claude/skills/review-code/phases/orchestrator.md +251 -0
  10. package/.claude/skills/review-code/phases/state-manager.md +752 -0
  11. package/.claude/skills/review-code/phases/state-schema.md +174 -0
  12. package/.claude/skills/review-code/specs/issue-classification.md +228 -0
  13. package/.claude/skills/review-code/specs/quality-standards.md +214 -0
  14. package/.claude/skills/review-code/specs/review-dimensions.md +337 -0
  15. package/.claude/skills/review-code/specs/rules/architecture-rules.json +63 -0
  16. package/.claude/skills/review-code/specs/rules/correctness-rules.json +60 -0
  17. package/.claude/skills/review-code/specs/rules/index.md +140 -0
  18. package/.claude/skills/review-code/specs/rules/performance-rules.json +59 -0
  19. package/.claude/skills/review-code/specs/rules/readability-rules.json +60 -0
  20. package/.claude/skills/review-code/specs/rules/security-rules.json +58 -0
  21. package/.claude/skills/review-code/specs/rules/testing-rules.json +59 -0
  22. package/.claude/skills/review-code/templates/issue-template.md +186 -0
  23. package/.claude/skills/review-code/templates/review-report.md +173 -0
  24. package/.claude/skills/skill-generator/SKILL.md +56 -17
  25. package/.claude/skills/skill-generator/templates/autonomous-orchestrator.md +10 -0
  26. package/.claude/skills/skill-generator/templates/sequential-phase.md +9 -0
  27. package/.claude/skills/skill-generator/templates/skill-md.md +84 -5
  28. package/.claude/workflows/cli-templates/schemas/solution-schema.json +3 -3
  29. package/ccw/src/templates/dashboard-js/views/issue-manager.js +8 -0
  30. package/package.json +1 -1
  31. package/.claude/skills/code-reviewer/README.md +0 -340
  32. package/.claude/skills/code-reviewer/SKILL.md +0 -308
  33. package/.claude/skills/code-reviewer/phases/01-code-discovery.md +0 -246
  34. package/.claude/skills/code-reviewer/phases/02-security-analysis.md +0 -442
  35. package/.claude/skills/code-reviewer/phases/03-best-practices-review.md +0 -36
  36. package/.claude/skills/code-reviewer/phases/04-report-generation.md +0 -278
  37. package/.claude/skills/code-reviewer/specs/best-practices-requirements.md +0 -346
  38. package/.claude/skills/code-reviewer/specs/quality-standards.md +0 -252
  39. package/.claude/skills/code-reviewer/specs/security-requirements.md +0 -243
  40. package/.claude/skills/code-reviewer/templates/best-practice-finding.md +0 -234
  41. package/.claude/skills/code-reviewer/templates/report-template.md +0 -316
  42. package/.claude/skills/code-reviewer/templates/security-finding.md +0 -161
@@ -0,0 +1,752 @@
1
+ # State Manager
2
+
3
+ Centralized state management module for Code Review workflow. Provides atomic operations, automatic backups, validation, and rollback capabilities.
4
+
5
+ ## Overview
6
+
7
+ This module solves the fragile state management problem by providing:
8
+ - **Atomic updates** - Write to temp file, then rename (prevents corruption)
9
+ - **Automatic backups** - Every update creates a backup first
10
+ - **Rollback capability** - Restore from backup on failure
11
+ - **Schema validation** - Ensure state structure integrity
12
+ - **Change history** - Track all state modifications
13
+
14
+ ## File Structure
15
+
16
+ ```
17
+ {workDir}/
18
+ state.json # Current state
19
+ state.backup.json # Latest backup
20
+ state-history.json # Change history log
21
+ ```
22
+
23
+ ## API Reference
24
+
25
+ ### initState(workDir)
26
+
27
+ Initialize a new state file with default values.
28
+
29
+ ```javascript
30
+ /**
31
+ * Initialize state file with default structure
32
+ * @param {string} workDir - Working directory path
33
+ * @returns {object} - Initial state object
34
+ */
35
+ function initState(workDir) {
36
+ const now = new Date().toISOString();
37
+
38
+ const initialState = {
39
+ status: 'pending',
40
+ started_at: now,
41
+ updated_at: now,
42
+ context: null,
43
+ scan_completed: false,
44
+ scan_summary: null,
45
+ reviewed_dimensions: [],
46
+ current_dimension: null,
47
+ findings: {
48
+ correctness: [],
49
+ readability: [],
50
+ performance: [],
51
+ security: [],
52
+ testing: [],
53
+ architecture: []
54
+ },
55
+ report_generated: false,
56
+ report_path: null,
57
+ current_action: null,
58
+ completed_actions: [],
59
+ errors: [],
60
+ error_count: 0,
61
+ summary: null
62
+ };
63
+
64
+ // Write state file
65
+ const statePath = `${workDir}/state.json`;
66
+ Write(statePath, JSON.stringify(initialState, null, 2));
67
+
68
+ // Initialize history log
69
+ const historyPath = `${workDir}/state-history.json`;
70
+ const historyEntry = {
71
+ entries: [{
72
+ timestamp: now,
73
+ action: 'init',
74
+ changes: { type: 'initialize', status: 'pending' }
75
+ }]
76
+ };
77
+ Write(historyPath, JSON.stringify(historyEntry, null, 2));
78
+
79
+ console.log(`[StateManager] Initialized state at ${statePath}`);
80
+ return initialState;
81
+ }
82
+ ```
83
+
84
+ ### getState(workDir)
85
+
86
+ Read and parse current state from file.
87
+
88
+ ```javascript
89
+ /**
90
+ * Read current state from file
91
+ * @param {string} workDir - Working directory path
92
+ * @returns {object|null} - Current state or null if not found
93
+ */
94
+ function getState(workDir) {
95
+ const statePath = `${workDir}/state.json`;
96
+
97
+ try {
98
+ const content = Read(statePath);
99
+ const state = JSON.parse(content);
100
+
101
+ // Validate structure before returning
102
+ const validation = validateState(state);
103
+ if (!validation.valid) {
104
+ console.warn(`[StateManager] State validation warnings: ${validation.warnings.join(', ')}`);
105
+ }
106
+
107
+ return state;
108
+ } catch (error) {
109
+ console.error(`[StateManager] Failed to read state: ${error.message}`);
110
+ return null;
111
+ }
112
+ }
113
+ ```
114
+
115
+ ### updateState(workDir, updates)
116
+
117
+ Safely update state with atomic write and automatic backup.
118
+
119
+ ```javascript
120
+ /**
121
+ * Safely update state with atomic write
122
+ * @param {string} workDir - Working directory path
123
+ * @param {object} updates - Partial state updates to apply
124
+ * @returns {object} - Updated state object
125
+ * @throws {Error} - If update fails (automatically rolls back)
126
+ */
127
+ function updateState(workDir, updates) {
128
+ const statePath = `${workDir}/state.json`;
129
+ const tempPath = `${workDir}/state.tmp.json`;
130
+ const backupPath = `${workDir}/state.backup.json`;
131
+ const historyPath = `${workDir}/state-history.json`;
132
+
133
+ // Step 1: Read current state
134
+ let currentState;
135
+ try {
136
+ currentState = JSON.parse(Read(statePath));
137
+ } catch (error) {
138
+ throw new Error(`Cannot read current state: ${error.message}`);
139
+ }
140
+
141
+ // Step 2: Create backup before any modification
142
+ try {
143
+ Write(backupPath, JSON.stringify(currentState, null, 2));
144
+ } catch (error) {
145
+ throw new Error(`Cannot create backup: ${error.message}`);
146
+ }
147
+
148
+ // Step 3: Merge updates
149
+ const now = new Date().toISOString();
150
+ const newState = deepMerge(currentState, {
151
+ ...updates,
152
+ updated_at: now
153
+ });
154
+
155
+ // Step 4: Validate new state
156
+ const validation = validateState(newState);
157
+ if (!validation.valid && validation.errors.length > 0) {
158
+ throw new Error(`Invalid state after update: ${validation.errors.join(', ')}`);
159
+ }
160
+
161
+ // Step 5: Write to temp file first (atomic preparation)
162
+ try {
163
+ Write(tempPath, JSON.stringify(newState, null, 2));
164
+ } catch (error) {
165
+ throw new Error(`Cannot write temp state: ${error.message}`);
166
+ }
167
+
168
+ // Step 6: Atomic rename (replace original with temp)
169
+ try {
170
+ // Read temp and write to original (simulating atomic rename)
171
+ const tempContent = Read(tempPath);
172
+ Write(statePath, tempContent);
173
+
174
+ // Clean up temp file
175
+ Bash(`rm -f "${tempPath}"`);
176
+ } catch (error) {
177
+ // Rollback: restore from backup
178
+ console.error(`[StateManager] Update failed, rolling back: ${error.message}`);
179
+ try {
180
+ const backup = Read(backupPath);
181
+ Write(statePath, backup);
182
+ } catch (rollbackError) {
183
+ throw new Error(`Critical: Update failed and rollback failed: ${rollbackError.message}`);
184
+ }
185
+ throw new Error(`Update failed, rolled back: ${error.message}`);
186
+ }
187
+
188
+ // Step 7: Record in history
189
+ try {
190
+ let history = { entries: [] };
191
+ try {
192
+ history = JSON.parse(Read(historyPath));
193
+ } catch (e) {
194
+ // History file may not exist, start fresh
195
+ }
196
+
197
+ history.entries.push({
198
+ timestamp: now,
199
+ action: 'update',
200
+ changes: summarizeChanges(currentState, newState, updates)
201
+ });
202
+
203
+ // Keep only last 100 entries
204
+ if (history.entries.length > 100) {
205
+ history.entries = history.entries.slice(-100);
206
+ }
207
+
208
+ Write(historyPath, JSON.stringify(history, null, 2));
209
+ } catch (error) {
210
+ // History logging failure is non-critical
211
+ console.warn(`[StateManager] Failed to log history: ${error.message}`);
212
+ }
213
+
214
+ console.log(`[StateManager] State updated successfully`);
215
+ return newState;
216
+ }
217
+
218
+ /**
219
+ * Deep merge helper - merges nested objects
220
+ */
221
+ function deepMerge(target, source) {
222
+ const result = { ...target };
223
+
224
+ for (const key of Object.keys(source)) {
225
+ if (source[key] === null || source[key] === undefined) {
226
+ result[key] = source[key];
227
+ } else if (Array.isArray(source[key])) {
228
+ result[key] = source[key];
229
+ } else if (typeof source[key] === 'object' && typeof target[key] === 'object') {
230
+ result[key] = deepMerge(target[key], source[key]);
231
+ } else {
232
+ result[key] = source[key];
233
+ }
234
+ }
235
+
236
+ return result;
237
+ }
238
+
239
+ /**
240
+ * Summarize changes for history logging
241
+ */
242
+ function summarizeChanges(oldState, newState, updates) {
243
+ const changes = {};
244
+
245
+ for (const key of Object.keys(updates)) {
246
+ if (key === 'updated_at') continue;
247
+
248
+ const oldVal = oldState[key];
249
+ const newVal = newState[key];
250
+
251
+ if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
252
+ changes[key] = {
253
+ from: typeof oldVal === 'object' ? '[object]' : oldVal,
254
+ to: typeof newVal === 'object' ? '[object]' : newVal
255
+ };
256
+ }
257
+ }
258
+
259
+ return changes;
260
+ }
261
+ ```
262
+
263
+ ### validateState(state)
264
+
265
+ Validate state structure against schema.
266
+
267
+ ```javascript
268
+ /**
269
+ * Validate state structure
270
+ * @param {object} state - State object to validate
271
+ * @returns {object} - { valid: boolean, errors: string[], warnings: string[] }
272
+ */
273
+ function validateState(state) {
274
+ const errors = [];
275
+ const warnings = [];
276
+
277
+ // Required fields
278
+ const requiredFields = ['status', 'started_at', 'updated_at'];
279
+ for (const field of requiredFields) {
280
+ if (state[field] === undefined) {
281
+ errors.push(`Missing required field: ${field}`);
282
+ }
283
+ }
284
+
285
+ // Status validation
286
+ const validStatuses = ['pending', 'running', 'completed', 'failed', 'user_exit'];
287
+ if (state.status && !validStatuses.includes(state.status)) {
288
+ errors.push(`Invalid status: ${state.status}. Must be one of: ${validStatuses.join(', ')}`);
289
+ }
290
+
291
+ // Timestamp format validation
292
+ const timestampFields = ['started_at', 'updated_at', 'completed_at'];
293
+ for (const field of timestampFields) {
294
+ if (state[field] && !isValidISOTimestamp(state[field])) {
295
+ warnings.push(`Invalid timestamp format for ${field}`);
296
+ }
297
+ }
298
+
299
+ // Findings structure validation
300
+ if (state.findings) {
301
+ const expectedDimensions = ['correctness', 'readability', 'performance', 'security', 'testing', 'architecture'];
302
+ for (const dim of expectedDimensions) {
303
+ if (!Array.isArray(state.findings[dim])) {
304
+ warnings.push(`findings.${dim} should be an array`);
305
+ }
306
+ }
307
+ }
308
+
309
+ // Context validation (when present)
310
+ if (state.context !== null && state.context !== undefined) {
311
+ const contextFields = ['target_path', 'files', 'language', 'total_lines', 'file_count'];
312
+ for (const field of contextFields) {
313
+ if (state.context[field] === undefined) {
314
+ warnings.push(`context.${field} is missing`);
315
+ }
316
+ }
317
+ }
318
+
319
+ // Error count validation
320
+ if (typeof state.error_count !== 'number') {
321
+ warnings.push('error_count should be a number');
322
+ }
323
+
324
+ // Array fields validation
325
+ const arrayFields = ['reviewed_dimensions', 'completed_actions', 'errors'];
326
+ for (const field of arrayFields) {
327
+ if (state[field] !== undefined && !Array.isArray(state[field])) {
328
+ errors.push(`${field} must be an array`);
329
+ }
330
+ }
331
+
332
+ return {
333
+ valid: errors.length === 0,
334
+ errors,
335
+ warnings
336
+ };
337
+ }
338
+
339
+ /**
340
+ * Check if string is valid ISO timestamp
341
+ */
342
+ function isValidISOTimestamp(str) {
343
+ if (typeof str !== 'string') return false;
344
+ const date = new Date(str);
345
+ return !isNaN(date.getTime()) && str.includes('T');
346
+ }
347
+ ```
348
+
349
+ ### backupState(workDir)
350
+
351
+ Create a manual backup of current state.
352
+
353
+ ```javascript
354
+ /**
355
+ * Create a manual backup of current state
356
+ * @param {string} workDir - Working directory path
357
+ * @param {string} [suffix] - Optional suffix for backup file name
358
+ * @returns {string} - Backup file path
359
+ */
360
+ function backupState(workDir, suffix = null) {
361
+ const statePath = `${workDir}/state.json`;
362
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
363
+ const backupName = suffix
364
+ ? `state.backup.${suffix}.json`
365
+ : `state.backup.${timestamp}.json`;
366
+ const backupPath = `${workDir}/${backupName}`;
367
+
368
+ try {
369
+ const content = Read(statePath);
370
+ Write(backupPath, content);
371
+ console.log(`[StateManager] Backup created: ${backupPath}`);
372
+ return backupPath;
373
+ } catch (error) {
374
+ throw new Error(`Failed to create backup: ${error.message}`);
375
+ }
376
+ }
377
+ ```
378
+
379
+ ### restoreState(workDir, backupPath)
380
+
381
+ Restore state from a backup file.
382
+
383
+ ```javascript
384
+ /**
385
+ * Restore state from a backup file
386
+ * @param {string} workDir - Working directory path
387
+ * @param {string} [backupPath] - Path to backup file (default: latest backup)
388
+ * @returns {object} - Restored state object
389
+ */
390
+ function restoreState(workDir, backupPath = null) {
391
+ const statePath = `${workDir}/state.json`;
392
+ const defaultBackup = `${workDir}/state.backup.json`;
393
+ const historyPath = `${workDir}/state-history.json`;
394
+
395
+ const sourcePath = backupPath || defaultBackup;
396
+
397
+ try {
398
+ // Read backup
399
+ const backupContent = Read(sourcePath);
400
+ const backupState = JSON.parse(backupContent);
401
+
402
+ // Validate backup state
403
+ const validation = validateState(backupState);
404
+ if (!validation.valid) {
405
+ throw new Error(`Backup state is invalid: ${validation.errors.join(', ')}`);
406
+ }
407
+
408
+ // Create backup of current state before restore (for safety)
409
+ try {
410
+ const currentContent = Read(statePath);
411
+ Write(`${workDir}/state.pre-restore.json`, currentContent);
412
+ } catch (e) {
413
+ // Current state may not exist, that's okay
414
+ }
415
+
416
+ // Update timestamp
417
+ const now = new Date().toISOString();
418
+ backupState.updated_at = now;
419
+
420
+ // Write restored state
421
+ Write(statePath, JSON.stringify(backupState, null, 2));
422
+
423
+ // Log to history
424
+ try {
425
+ let history = { entries: [] };
426
+ try {
427
+ history = JSON.parse(Read(historyPath));
428
+ } catch (e) {}
429
+
430
+ history.entries.push({
431
+ timestamp: now,
432
+ action: 'restore',
433
+ changes: { source: sourcePath }
434
+ });
435
+
436
+ Write(historyPath, JSON.stringify(history, null, 2));
437
+ } catch (e) {
438
+ console.warn(`[StateManager] Failed to log restore to history`);
439
+ }
440
+
441
+ console.log(`[StateManager] State restored from ${sourcePath}`);
442
+ return backupState;
443
+ } catch (error) {
444
+ throw new Error(`Failed to restore state: ${error.message}`);
445
+ }
446
+ }
447
+ ```
448
+
449
+ ## Convenience Functions
450
+
451
+ ### getNextDimension(state)
452
+
453
+ Get the next dimension to review based on current state.
454
+
455
+ ```javascript
456
+ /**
457
+ * Get next dimension to review
458
+ * @param {object} state - Current state
459
+ * @returns {string|null} - Next dimension or null if all reviewed
460
+ */
461
+ function getNextDimension(state) {
462
+ const dimensions = ['correctness', 'security', 'performance', 'readability', 'testing', 'architecture'];
463
+ const reviewed = state.reviewed_dimensions || [];
464
+
465
+ for (const dim of dimensions) {
466
+ if (!reviewed.includes(dim)) {
467
+ return dim;
468
+ }
469
+ }
470
+
471
+ return null;
472
+ }
473
+ ```
474
+
475
+ ### addFinding(workDir, finding)
476
+
477
+ Add a new finding to the state.
478
+
479
+ ```javascript
480
+ /**
481
+ * Add a finding to the appropriate dimension
482
+ * @param {string} workDir - Working directory path
483
+ * @param {object} finding - Finding object (must include dimension field)
484
+ * @returns {object} - Updated state
485
+ */
486
+ function addFinding(workDir, finding) {
487
+ if (!finding.dimension) {
488
+ throw new Error('Finding must have a dimension field');
489
+ }
490
+
491
+ const state = getState(workDir);
492
+ const dimension = finding.dimension;
493
+
494
+ // Generate ID if not provided
495
+ if (!finding.id) {
496
+ const prefixes = {
497
+ correctness: 'CORR',
498
+ readability: 'READ',
499
+ performance: 'PERF',
500
+ security: 'SEC',
501
+ testing: 'TEST',
502
+ architecture: 'ARCH'
503
+ };
504
+ const prefix = prefixes[dimension] || 'MISC';
505
+ const count = (state.findings[dimension]?.length || 0) + 1;
506
+ finding.id = `${prefix}-${String(count).padStart(3, '0')}`;
507
+ }
508
+
509
+ const currentFindings = state.findings[dimension] || [];
510
+
511
+ return updateState(workDir, {
512
+ findings: {
513
+ ...state.findings,
514
+ [dimension]: [...currentFindings, finding]
515
+ }
516
+ });
517
+ }
518
+ ```
519
+
520
+ ### markDimensionComplete(workDir, dimension)
521
+
522
+ Mark a dimension as reviewed.
523
+
524
+ ```javascript
525
+ /**
526
+ * Mark a dimension as reviewed
527
+ * @param {string} workDir - Working directory path
528
+ * @param {string} dimension - Dimension name
529
+ * @returns {object} - Updated state
530
+ */
531
+ function markDimensionComplete(workDir, dimension) {
532
+ const state = getState(workDir);
533
+ const reviewed = state.reviewed_dimensions || [];
534
+
535
+ if (reviewed.includes(dimension)) {
536
+ console.warn(`[StateManager] Dimension ${dimension} already marked as reviewed`);
537
+ return state;
538
+ }
539
+
540
+ return updateState(workDir, {
541
+ reviewed_dimensions: [...reviewed, dimension],
542
+ current_dimension: null
543
+ });
544
+ }
545
+ ```
546
+
547
+ ### recordError(workDir, action, message)
548
+
549
+ Record an error in state.
550
+
551
+ ```javascript
552
+ /**
553
+ * Record an execution error
554
+ * @param {string} workDir - Working directory path
555
+ * @param {string} action - Action that failed
556
+ * @param {string} message - Error message
557
+ * @returns {object} - Updated state
558
+ */
559
+ function recordError(workDir, action, message) {
560
+ const state = getState(workDir);
561
+ const errors = state.errors || [];
562
+ const errorCount = (state.error_count || 0) + 1;
563
+
564
+ const newError = {
565
+ action,
566
+ message,
567
+ timestamp: new Date().toISOString()
568
+ };
569
+
570
+ const newState = updateState(workDir, {
571
+ errors: [...errors, newError],
572
+ error_count: errorCount
573
+ });
574
+
575
+ // Auto-fail if error count exceeds threshold
576
+ if (errorCount >= 3) {
577
+ return updateState(workDir, {
578
+ status: 'failed'
579
+ });
580
+ }
581
+
582
+ return newState;
583
+ }
584
+ ```
585
+
586
+ ## Usage Examples
587
+
588
+ ### Initialize and Run Review
589
+
590
+ ```javascript
591
+ // Initialize new review session
592
+ const workDir = '/path/to/review-session';
593
+ const state = initState(workDir);
594
+
595
+ // Update status to running
596
+ updateState(workDir, { status: 'running' });
597
+
598
+ // After collecting context
599
+ updateState(workDir, {
600
+ context: {
601
+ target_path: '/src/auth',
602
+ files: ['auth.ts', 'login.ts'],
603
+ language: 'typescript',
604
+ total_lines: 500,
605
+ file_count: 2
606
+ }
607
+ });
608
+
609
+ // After completing quick scan
610
+ updateState(workDir, {
611
+ scan_completed: true,
612
+ scan_summary: {
613
+ risk_areas: [{ file: 'auth.ts', reason: 'Complex logic', priority: 'high' }],
614
+ complexity_score: 7.5,
615
+ quick_issues: []
616
+ }
617
+ });
618
+ ```
619
+
620
+ ### Add Findings During Review
621
+
622
+ ```javascript
623
+ // Add a security finding
624
+ addFinding(workDir, {
625
+ dimension: 'security',
626
+ severity: 'high',
627
+ category: 'injection',
628
+ file: 'auth.ts',
629
+ line: 45,
630
+ description: 'SQL injection vulnerability',
631
+ recommendation: 'Use parameterized queries'
632
+ });
633
+
634
+ // Mark dimension complete
635
+ markDimensionComplete(workDir, 'security');
636
+ ```
637
+
638
+ ### Error Handling with Rollback
639
+
640
+ ```javascript
641
+ try {
642
+ updateState(workDir, {
643
+ status: 'running',
644
+ current_action: 'deep-review'
645
+ });
646
+
647
+ // ... do review work ...
648
+
649
+ } catch (error) {
650
+ // Record error
651
+ recordError(workDir, 'deep-review', error.message);
652
+
653
+ // If needed, restore from backup
654
+ restoreState(workDir);
655
+ }
656
+ ```
657
+
658
+ ### Check Review Progress
659
+
660
+ ```javascript
661
+ const state = getState(workDir);
662
+ const nextDim = getNextDimension(state);
663
+
664
+ if (nextDim) {
665
+ console.log(`Next dimension to review: ${nextDim}`);
666
+ updateState(workDir, { current_dimension: nextDim });
667
+ } else {
668
+ console.log('All dimensions reviewed');
669
+ }
670
+ ```
671
+
672
+ ## Integration with Orchestrator
673
+
674
+ Update the orchestrator to use StateManager:
675
+
676
+ ```javascript
677
+ // In orchestrator.md - Replace direct state operations with StateManager calls
678
+
679
+ // OLD:
680
+ const state = JSON.parse(Read(`${workDir}/state.json`));
681
+
682
+ // NEW:
683
+ const state = getState(workDir);
684
+
685
+ // OLD:
686
+ function updateState(updates) {
687
+ const state = JSON.parse(Read(`${workDir}/state.json`));
688
+ const newState = { ...state, ...updates, updated_at: new Date().toISOString() };
689
+ Write(`${workDir}/state.json`, JSON.stringify(newState, null, 2));
690
+ return newState;
691
+ }
692
+
693
+ // NEW:
694
+ // Import from state-manager.md
695
+ // updateState(workDir, updates) - handles atomic write, backup, validation
696
+
697
+ // Error handling - OLD:
698
+ updateState({
699
+ errors: [...(state.errors || []), { action: actionId, message: error.message, timestamp: new Date().toISOString() }],
700
+ error_count: (state.error_count || 0) + 1
701
+ });
702
+
703
+ // Error handling - NEW:
704
+ recordError(workDir, actionId, error.message);
705
+ ```
706
+
707
+ ## State History Format
708
+
709
+ The `state-history.json` file tracks all state changes:
710
+
711
+ ```json
712
+ {
713
+ "entries": [
714
+ {
715
+ "timestamp": "2024-01-01T10:00:00.000Z",
716
+ "action": "init",
717
+ "changes": { "type": "initialize", "status": "pending" }
718
+ },
719
+ {
720
+ "timestamp": "2024-01-01T10:01:00.000Z",
721
+ "action": "update",
722
+ "changes": {
723
+ "status": { "from": "pending", "to": "running" },
724
+ "current_action": { "from": null, "to": "action-collect-context" }
725
+ }
726
+ },
727
+ {
728
+ "timestamp": "2024-01-01T10:05:00.000Z",
729
+ "action": "restore",
730
+ "changes": { "source": "/path/state.backup.json" }
731
+ }
732
+ ]
733
+ }
734
+ ```
735
+
736
+ ## Error Recovery Strategies
737
+
738
+ | Scenario | Strategy | Function |
739
+ |----------|----------|----------|
740
+ | State file corrupted | Restore from backup | `restoreState(workDir)` |
741
+ | Invalid state after update | Auto-rollback (built-in) | N/A (automatic) |
742
+ | Multiple errors | Auto-fail after 3 | `recordError()` |
743
+ | Need to retry from checkpoint | Restore specific backup | `restoreState(workDir, backupPath)` |
744
+ | Review interrupted | Resume from saved state | `getState(workDir)` |
745
+
746
+ ## Best Practices
747
+
748
+ 1. **Always use `updateState()`** - Never write directly to state.json
749
+ 2. **Check validation warnings** - Warnings may indicate data issues
750
+ 3. **Use convenience functions** - `addFinding()`, `markDimensionComplete()`, etc.
751
+ 4. **Monitor history** - Check state-history.json for debugging
752
+ 5. **Create named backups** - Before major operations: `backupState(workDir, 'pre-deep-review')`