| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- from __future__ import annotations
- import json
- from dataclasses import dataclass
- from pathlib import Path
- ARCHIVE_ROOT = Path(__file__).resolve().parent.parent / 'archive' / 'claude_code_ts_snapshot' / 'src'
- CURRENT_ROOT = Path(__file__).resolve().parent
- REFERENCE_SURFACE_PATH = CURRENT_ROOT / 'reference_data' / 'archive_surface_snapshot.json'
- COMMAND_SNAPSHOT_PATH = CURRENT_ROOT / 'reference_data' / 'commands_snapshot.json'
- TOOL_SNAPSHOT_PATH = CURRENT_ROOT / 'reference_data' / 'tools_snapshot.json'
- ARCHIVE_ROOT_FILES = {
- 'QueryEngine.ts': 'QueryEngine.py',
- 'Task.ts': 'task.py',
- 'Tool.ts': 'Tool.py',
- 'commands.ts': 'commands.py',
- 'context.ts': 'context.py',
- 'cost-tracker.ts': 'cost_tracker.py',
- 'costHook.ts': 'costHook.py',
- 'dialogLaunchers.tsx': 'dialogLaunchers.py',
- 'history.ts': 'history.py',
- 'ink.ts': 'ink.py',
- 'interactiveHelpers.tsx': 'interactiveHelpers.py',
- 'main.tsx': 'main.py',
- 'projectOnboardingState.ts': 'projectOnboardingState.py',
- 'query.ts': 'query.py',
- 'replLauncher.tsx': 'replLauncher.py',
- 'setup.ts': 'setup.py',
- 'tasks.ts': 'tasks.py',
- 'tools.ts': 'tools.py',
- }
- ARCHIVE_DIR_MAPPINGS = {
- 'assistant': 'assistant',
- 'bootstrap': 'bootstrap',
- 'bridge': 'bridge',
- 'buddy': 'buddy',
- 'cli': 'cli',
- 'commands': 'commands.py',
- 'components': 'components',
- 'constants': 'constants',
- 'context': 'context.py',
- 'coordinator': 'coordinator',
- 'entrypoints': 'entrypoints',
- 'hooks': 'hooks',
- 'ink': 'ink.py',
- 'keybindings': 'keybindings',
- 'memdir': 'memdir',
- 'migrations': 'migrations',
- 'moreright': 'moreright',
- 'native-ts': 'native_ts',
- 'outputStyles': 'outputStyles',
- 'plugins': 'plugins',
- 'query': 'query.py',
- 'remote': 'remote',
- 'schemas': 'schemas',
- 'screens': 'screens',
- 'server': 'server',
- 'services': 'services',
- 'skills': 'skills',
- 'state': 'state',
- 'tasks': 'tasks.py',
- 'tools': 'tools.py',
- 'types': 'types',
- 'upstreamproxy': 'upstreamproxy',
- 'utils': 'utils',
- 'vim': 'vim',
- 'voice': 'voice',
- }
- @dataclass(frozen=True)
- class ParityAuditResult:
- archive_present: bool
- root_file_coverage: tuple[int, int]
- directory_coverage: tuple[int, int]
- total_file_ratio: tuple[int, int]
- command_entry_ratio: tuple[int, int]
- tool_entry_ratio: tuple[int, int]
- missing_root_targets: tuple[str, ...]
- missing_directory_targets: tuple[str, ...]
- def to_markdown(self) -> str:
- lines = ['# Parity Audit']
- if not self.archive_present:
- lines.append('Local archive unavailable; parity audit cannot compare against the original snapshot.')
- return '\n'.join(lines)
- lines.extend([
- '',
- f'Root file coverage: **{self.root_file_coverage[0]}/{self.root_file_coverage[1]}**',
- f'Directory coverage: **{self.directory_coverage[0]}/{self.directory_coverage[1]}**',
- f'Total Python files vs archived TS-like files: **{self.total_file_ratio[0]}/{self.total_file_ratio[1]}**',
- f'Command entry coverage: **{self.command_entry_ratio[0]}/{self.command_entry_ratio[1]}**',
- f'Tool entry coverage: **{self.tool_entry_ratio[0]}/{self.tool_entry_ratio[1]}**',
- '',
- 'Missing root targets:',
- ])
- if self.missing_root_targets:
- lines.extend(f'- {item}' for item in self.missing_root_targets)
- else:
- lines.append('- none')
- lines.extend(['', 'Missing directory targets:'])
- if self.missing_directory_targets:
- lines.extend(f'- {item}' for item in self.missing_directory_targets)
- else:
- lines.append('- none')
- return '\n'.join(lines)
- def _reference_surface() -> dict[str, object]:
- return json.loads(REFERENCE_SURFACE_PATH.read_text())
- def _snapshot_count(path: Path) -> int:
- return len(json.loads(path.read_text()))
- def run_parity_audit() -> ParityAuditResult:
- current_entries = {path.name for path in CURRENT_ROOT.iterdir()}
- root_hits = [target for target in ARCHIVE_ROOT_FILES.values() if target in current_entries]
- dir_hits = [target for target in ARCHIVE_DIR_MAPPINGS.values() if target in current_entries]
- missing_roots = tuple(target for target in ARCHIVE_ROOT_FILES.values() if target not in current_entries)
- missing_dirs = tuple(target for target in ARCHIVE_DIR_MAPPINGS.values() if target not in current_entries)
- current_python_files = sum(1 for path in CURRENT_ROOT.rglob('*.py') if path.is_file())
- reference = _reference_surface()
- return ParityAuditResult(
- archive_present=ARCHIVE_ROOT.exists(),
- root_file_coverage=(len(root_hits), len(ARCHIVE_ROOT_FILES)),
- directory_coverage=(len(dir_hits), len(ARCHIVE_DIR_MAPPINGS)),
- total_file_ratio=(current_python_files, int(reference['total_ts_like_files'])),
- command_entry_ratio=(_snapshot_count(COMMAND_SNAPSHOT_PATH), int(reference['command_entry_count'])),
- tool_entry_ratio=(_snapshot_count(TOOL_SNAPSHOT_PATH), int(reference['tool_entry_count'])),
- missing_root_targets=missing_roots,
- missing_directory_targets=missing_dirs,
- )
|