diff --git a/agents/antigravity/done/TASK-2026-08-18-consolidation.md b/agents/antigravity/done/TASK-2026-08-18-consolidation.md new file mode 100644 index 0000000..62e0c31 --- /dev/null +++ b/agents/antigravity/done/TASK-2026-08-18-consolidation.md @@ -0,0 +1,19 @@ +# TASK-2026-08-18-консолидация-рабочего-пространства + +**Дата:** 2026-08-18 +**От:** владелец проекта (через Claude) +**Статус:** in-progress + +## Цель +Склонировать 17 репозиториев ochenstarik-ui в E:\Agent projects и проверить структуру agents/ в каждом. + +## Репозитории +business-platform, kagent, hermes-config-backup, server-monitor-manager, +randomayzer, trade-signal-platform, trading-knowledge-base, +finance-telegram-bot, agent-control-center, agent-control-center-server, +lightweight-server, safetest-platform, agent-engineering-quality-system, +hermes-lossless-context-layer, hermes-task-inbox, singbox-ai-router, +trade-signal-bot-legacy + +## Отчёт +E:\Agent projects\done\2026-08-18-консолидация-рабочего-пространства.md diff --git a/agents/antigravity/done/TASK-2026-08-18-security-review-exporter.md b/agents/antigravity/done/TASK-2026-08-18-security-review-exporter.md new file mode 100644 index 0000000..09778cb --- /dev/null +++ b/agents/antigravity/done/TASK-2026-08-18-security-review-exporter.md @@ -0,0 +1,18 @@ +# Task Done: Developer Tooling — Add Security Review Exporter + +**Status:** DONE +**Assigned to:** Antigravity (@orchestrator) +**Date:** 2026-08-18 +**Base Commit:** `bc2b658` + +## Accomplished +1. Created `tools/export-review.ps1` supporting: + - Full snapshot mode (`git archive HEAD`) with `REVIEW_CONTEXT.md` injection. + - Diff mode (`-Diff`, `-Base `) with `REVIEW_DIFF.patch`, `REVIEW_CHANGED_FILES.txt`, changed source files in tree structure, all tests in `tests/*`, `prisma/schema.prisma`, `package.json`, `docs/*`. + - Security safety check against tracked secrets (`.env`, `*.pem`, `*.key`, `credentials.json`, `secrets.json`). + - Dirty worktree handling with warning and `-RequireClean` strict guard. + - Output summary table with file count, size, commit SHA, mode. + - `-CopyPrompt` to automatically put Russian reviewer prompt into Windows clipboard. + - Compatible with Windows PowerShell 5.1 and PowerShell 7+, handles paths with spaces. +2. Created user documentation in `docs/AI_REVIEW_EXPORT.md`. +3. Verified both FULL and DIFF exports, tested `-RequireClean`, tested Windows PowerShell 5.1 and PowerShell 7. diff --git a/docs/AI_REVIEW_EXPORT.md b/docs/AI_REVIEW_EXPORT.md new file mode 100644 index 0000000..a50f941 --- /dev/null +++ b/docs/AI_REVIEW_EXPORT.md @@ -0,0 +1,91 @@ +# Randomayzer AI Security Review Exporter + +`tools/export-review.ps1` — утилита для создания автономных snapshot и diff пакетов репозитория для внешних AI security reviewers, у которых нет прямого доступа к GitHub репозиторию или локальной файловой системе. + +--- + +## 1. Возможности + +- **Full Snapshot Mode (по умолчанию)**: Создает полный ZIP-архив репозитория на основе `git archive HEAD`. +- **Diff Mode (`-Diff`)**: Создает компактный пакет изменений между базовым коммитом (`-Base`) и `HEAD`, включая патч, список измененных файлов, измененные исходники, полный набор тестов, схему базы данных и документацию. +- **Review Context (`REVIEW_CONTEXT.md`)**: В каждый архив автоматически встраивается файл метаданных с полным SHA, веткой, временной меткой, состоянием working tree и статистикой `git log`. +- **Secret Safety Check**: Проверяет tracked-файлы на наличие потенциальных секретов (`.env`, `*.pem`, `*.key`, `credentials.json`, `secrets.json`) и блокирует экспорт при обнаружении. +- **Dirty Worktree Warning / Guard**: Предупреждает о наличии незакоммиченных изменений (снапшот собирается строго из `HEAD`) или прерывает выполнение при флаге `-RequireClean`. +- **Zero External Dependencies**: Работает на Windows PowerShell 5.1 и PowerShell 7+ с использованием стандартных API .NET (`System.IO.Compression`). Сторонние архиваторы (7-Zip, WinRAR) не требуются. +- **Корректная работа с пробелами в путях** (например, `E:\Agent projects\Randomayzer`). + +--- + +## 2. Быстрый старт + +Запуск из корня проекта: + +### Полный снимок репозитория (Full Snapshot) +```powershell +.\tools\export-review.ps1 +``` +Архив сохраняется по умолчанию в папку `Desktop\Randomayzer Reviews\randomayzer-review-.zip`. + +### Diff последнего коммита (`HEAD^` vs `HEAD`) +```powershell +.\tools\export-review.ps1 -Diff +``` +Создает архив `randomayzer-diff-review-.zip`, содержащий: +- `REVIEW_CONTEXT.md` +- `REVIEW_DIFF.patch` +- `REVIEW_CHANGED_FILES.txt` +- Измененные файлы в структуре каталогов проекта +- Полный набор тестов `tests/*` +- Схему `prisma/schema.prisma`, `package.json`, `.env.example`, документацию `docs/*` + +### Diff от определенного коммита +```powershell +.\tools\export-review.ps1 -Diff -Base b5467f6 +``` + +--- + +## 3. Параметры + +| Параметр | Тип | Описание | +|---|---|---| +| `-Diff` | Switch | Включает режим формирования diff-пакета вместо полного снимка. | +| `-Base ` | String | Базовый коммит для сравнения в режиме `-Diff` (по умолчанию `HEAD^`). | +| `-OutputDir ` | String | Пользовательский путь для сохранения ZIP-файлов (по умолчанию `Desktop\Randomayzer Reviews\`). | +| `-RequireClean` | Switch | Завершает работу с ошибкой, если в working tree есть незакоммиченные файлы. | +| `-AllowSensitiveTrackedFiles` | Switch | Отключает блокировку экспорта при обнаружении подозрительных tracked-файлов. | +| `-CopyPrompt` | Switch | Автоматически копирует в буфер обмена Windows текст задания для security reviewer. | + +--- + +## 4. Примеры использования + +### Экспорт со строгой проверкой чистоты рабочей директории +```powershell +.\tools\export-review.ps1 -RequireClean +``` + +### Экспорт в пользовательскую директорию с копированием промпта +```powershell +.\tools\export-review.ps1 -Diff -Base bc2b658 -OutputDir "D:\Audits" -CopyPrompt +``` + +После выполнения в буфере обмена будет готов стандартизированный промпт: +> «В приложенном архиве snapshot Randomayzer на commit ``. +> Используй архив как source of truth. +> Не используй GitHub HEAD вместо него. +> Выполни ранее выданное security review задание.» + +--- + +## 5. Гарантии безопасности архива + +1. **Изоляция от локального мусора**: В ZIP-архив **никогда не попадают**: + - `.git` + - `node_modules` + - `.next` сборки и кэш + - Локальные незакоммиченные файлы + - Локальные `.env`, `.env.local` + - IDE-файлы (`.vscode`, `.idea`) +2. **Точность снимка**: Файлы извлекаются напрямую из Git-объектов коммита (`git archive` для Full или `git show HEAD:` для Diff), поэтому локальные изменения в рабочей директории не искажают снимок. +3. **Защита от утечки секретов**: Сканирование имен файлов блокирует экспорт при случайном попадании приватных ключей или файлов конфигурации в индекс Git. diff --git a/tools/export-review.ps1 b/tools/export-review.ps1 new file mode 100644 index 0000000..49b56e5 --- /dev/null +++ b/tools/export-review.ps1 @@ -0,0 +1,410 @@ +<# +.SYNOPSIS + Exports Randomayzer repository snapshots and diff packages for AI Security Reviewers. + +.DESCRIPTION + Creates clean, deterministic ZIP archives of tracked repository code at a specific commit. + Guarantees that node_modules, local .env files, untracked artifacts, and IDE caches are never included. + Includes automated REVIEW_CONTEXT.md, diffs, and verification metrics. + +.PARAMETER Diff + Generate a diff review package between Base commit and HEAD instead of a full snapshot. + +.PARAMETER Base + Base commit for diff mode (defaults to HEAD^). + +.PARAMETER OutputDir + Output directory for the generated ZIP file (defaults to Desktop\Randomayzer Reviews\). + +.PARAMETER RequireClean + If specified, aborts the export if the git working tree has uncommitted changes. + +.PARAMETER AllowSensitiveTrackedFiles + Bypasses the safety abort when potentially sensitive file patterns are detected in tracked git files. + +.PARAMETER CopyPrompt + Copies the standardized security reviewer instructions to the Windows clipboard upon completion. + +.EXAMPLE + .\tools\export-review.ps1 + +.EXAMPLE + .\tools\export-review.ps1 -Diff + +.EXAMPLE + .\tools\export-review.ps1 -Diff -Base bc2b658 -CopyPrompt + +.EXAMPLE + .\tools\export-review.ps1 -OutputDir "D:\Audits" -RequireClean +#> + +[CmdletBinding()] +param( + [switch]$Diff, + [string]$Base, + [string]$OutputDir, + [switch]$RequireClean, + [switch]$AllowSensitiveTrackedFiles, + [switch]$CopyPrompt +) + +$ErrorActionPreference = "Stop" + +# 1. Resolve Git repository root and metadata +$gitRootRaw = git rev-parse --show-toplevel 2>$null +if (-not $gitRootRaw -or $LASTEXITCODE -ne 0) { + Write-Error "Not inside a git repository or git is unavailable." + exit 1 +} +$gitRoot = [System.IO.Path]::GetFullPath($gitRootRaw.Trim()) + +$headSha = (git rev-parse HEAD 2>$null).Trim() +$shortSha = (git rev-parse --short HEAD 2>$null).Trim() +$branch = (git rev-parse --abbrev-ref HEAD 2>$null).Trim() + +$remoteUrl = (git config --get remote.origin.url 2>$null) +if (-not $remoteUrl) { + $remoteUrl = "https://github.com/ochenstarik-ui/randomayzer" +} else { + $remoteUrl = $remoteUrl.Trim() +} + +# 2. Output directory resolution (relative to current PowerShell location) +if (-not $OutputDir) { + $desktopPath = [Environment]::GetFolderPath([Environment+SpecialFolder]::Desktop) + $OutputDir = [System.IO.Path]::Combine($desktopPath, "Randomayzer Reviews") +} else { + if (-not [System.IO.Path]::IsPathRooted($OutputDir)) { + $OutputDir = [System.IO.Path]::Combine((Get-Location).Path, $OutputDir) + } + $OutputDir = [System.IO.Path]::GetFullPath($OutputDir) +} + +if (-not (Test-Path -LiteralPath $OutputDir)) { + New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null +} + +# 3. Dirty worktree check +$statusOutput = git status --porcelain +$isDirty = [bool]($statusOutput -and ($statusOutput.Trim().Length -gt 0)) + +if ($isDirty) { + if ($RequireClean) { + Write-Error "Working tree contains uncommitted changes. -RequireClean was specified. Aborting export." + exit 1 + } else { + Write-Warning "Working tree contains uncommitted changes. Snapshot represents committed HEAD only." + } +} +$dirtyText = if ($isDirty) { "YES" } else { "NO" } + +# 4. Secret safety check on tracked files +$trackedFiles = git ls-tree -r --name-only HEAD +$sensitiveMatches = @() +$sensitiveRegex = '(?i)(^|/|\\)(\.env(\.(?!example$).*)?|\.env$|.*\.pem$|.*\.key$|credentials\.json$|secrets\.json$|.*\.p12$|.*\.pfx$)' + +foreach ($file in $trackedFiles) { + if ($file -match $sensitiveRegex -and $file -notmatch '(?i)\.env\.example') { + $sensitiveMatches += $file + } +} + +if ($sensitiveMatches.Count -gt 0) { + Write-Warning "==================================================" + Write-Warning "POTENTIALLY SENSITIVE FILES DETECTED IN TRACKED GIT:" + foreach ($sf in $sensitiveMatches) { + Write-Warning " - $sf" + } + Write-Warning "==================================================" + if (-not $AllowSensitiveTrackedFiles) { + Write-Error "Export aborted to prevent secret leakage. Pass -AllowSensitiveTrackedFiles to override." + exit 1 + } +} + +# Ensure .NET compression assemblies are loaded +Add-Type -AssemblyName System.IO.Compression +Add-Type -AssemblyName System.IO.Compression.FileSystem + +$timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss zzz") +$utf8NoBom = New-Object System.Text.UTF8Encoding($false) + +# 5. Export generation +if (-not $Diff) { + # ── FULL SNAPSHOT MODE ── + $modeName = "FULL" + $zipFileName = "randomayzer-review-$shortSha.zip" + $zipFilePath = [System.IO.Path]::Combine($OutputDir, $zipFileName) + + if (Test-Path -LiteralPath $zipFilePath) { + Remove-Item -LiteralPath $zipFilePath -Force + } + + # Build clean archive directly from git HEAD + Push-Location $gitRoot + try { + git archive HEAD --format=zip --output="$zipFilePath" + if ($LASTEXITCODE -ne 0) { + Write-Error "git archive failed with exit code $LASTEXITCODE" + exit 1 + } + } finally { + Pop-Location + } + + # Generate metadata context + $gitLogStat = (git log -1 --stat HEAD) -join "`n" + + $reviewContextLines = @( + "# Randomayzer Review Snapshot", + "", + "- **Full commit SHA:** $headSha", + "- **Short SHA:** $shortSha", + "- **Branch:** $branch", + "- **Generated at:** $timestamp", + "- **Repository:** $remoteUrl", + "- **Snapshot mode:** FULL", + "- **Working tree dirty at export time:** $dirtyText", + "", + "## Source of Truth", + "The files in this archive are the exact tracked repository snapshot for the commit shown above.", + "", + "## Reviewer Instructions", + "Do not use GitHub HEAD as source of truth.", + "Review the attached snapshot.", + "", + "## Recent Commit Log", + '```', + $gitLogStat, + '```' + ) + $reviewContext = $reviewContextLines -join "`n" + + # Inject REVIEW_CONTEXT.md into ZIP + $archive = [System.IO.Compression.ZipFile]::Open($zipFilePath, [System.IO.Compression.ZipArchiveMode]::Update) + try { + $existingEntry = $archive.GetEntry("REVIEW_CONTEXT.md") + if ($existingEntry) { + $existingEntry.Delete() + } + $entry = $archive.CreateEntry("REVIEW_CONTEXT.md", [System.IO.Compression.CompressionLevel]::Optimal) + $stream = $entry.Open() + try { + $bytes = $utf8NoBom.GetBytes($reviewContext) + $stream.Write($bytes, 0, $bytes.Length) + } finally { + $stream.Dispose() + } + } finally { + $archive.Dispose() + } + +} else { + # ── DIFF MODE ── + $modeName = "DIFF" + $zipFileName = "randomayzer-diff-review-$shortSha.zip" + $zipFilePath = [System.IO.Path]::Combine($OutputDir, $zipFileName) + + if (Test-Path -LiteralPath $zipFilePath) { + Remove-Item -LiteralPath $zipFilePath -Force + } + + if (-not $Base) { + $Base = "HEAD^" + } + + $baseShaRaw = git rev-parse --verify "$Base" 2>$null + if (-not $baseShaRaw -or $LASTEXITCODE -ne 0) { + Write-Error "Invalid base commit: '$Base'" + exit 1 + } + $baseSha = $baseShaRaw.Trim() + $baseShortSha = (git rev-parse --short $baseSha 2>$null).Trim() + + # Generate diff and list of changed files + $diffPatch = (git diff $baseSha HEAD) -join "`n" + $changedFiles = git diff --name-only $baseSha HEAD + $changedFilesList = @() + if ($changedFiles) { + $changedFilesList = @($changedFiles) | Where-Object { $_ -and $_.Trim().Length -gt 0 } + } + $changedFilesText = ($changedFilesList -join "`n") + + # Determine files to include in Diff package: + # 1. Changed files present in HEAD (exclude deleted files) + # 2. All tracked test files (tests/*) + # 3. Security, config, and documentation context files + $trackedHeadFiles = git ls-tree -r --name-only HEAD + $filesToInclude = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) + + foreach ($cf in $changedFilesList) { + if ($trackedHeadFiles -contains $cf) { + $filesToInclude.Add($cf) | Out-Null + } + } + + # Add all tracked test files for test integrity review + foreach ($tf in $trackedHeadFiles) { + if ($tf -like "tests/*" -or $tf -like "test/*") { + $filesToInclude.Add($tf) | Out-Null + } + } + + # Add schema, dependencies, env.example, and documentation + $contextPatterns = @( + "package.json", + "package-lock.json", + "prisma/schema.prisma", + ".env.example", + "README.md", + "AGENTS.md", + "GEMINI.md", + "docs/*" + ) + + foreach ($pattern in $contextPatterns) { + foreach ($hf in $trackedHeadFiles) { + if ($hf -like $pattern) { + # Security filter + if ($hf -match $sensitiveRegex -and $hf -notmatch '(?i)\.env\.example') { + continue + } + $filesToInclude.Add($hf) | Out-Null + } + } + } + + # Stage files in temporary directory + $tempDir = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), ("randomayzer_export_" + [System.Guid]::NewGuid().ToString("N"))) + New-Item -ItemType Directory -Path $tempDir -Force | Out-Null + + try { + Push-Location $gitRoot + try { + foreach ($relPath in $filesToInclude) { + $gitRelPath = $relPath -replace '\\', '/' + $destPath = [System.IO.Path]::Combine($tempDir, ($relPath -replace '/', [System.IO.Path]::DirectorySeparatorChar)) + $destParent = [System.IO.Path]::GetDirectoryName($destPath) + if (-not (Test-Path -LiteralPath $destParent)) { + New-Item -ItemType Directory -Path $destParent -Force | Out-Null + } + + # Extract exact binary content from HEAD + $processInfo = New-Object System.Diagnostics.ProcessStartInfo + $processInfo.FileName = "git" + $processInfo.Arguments = "show `"HEAD:$gitRelPath`"" + $processInfo.WorkingDirectory = $gitRoot + $processInfo.UseShellExecute = $false + $processInfo.RedirectStandardOutput = $true + $processInfo.RedirectStandardError = $true + $processInfo.CreateNoWindow = $true + + $process = [System.Diagnostics.Process]::Start($processInfo) + $outputStream = [System.IO.File]::Create($destPath) + try { + $process.StandardOutput.BaseStream.CopyTo($outputStream) + } finally { + $outputStream.Dispose() + } + $process.WaitForExit() + } + } finally { + Pop-Location + } + + # Write diff artifacts + [System.IO.File]::WriteAllText([System.IO.Path]::Combine($tempDir, "REVIEW_DIFF.patch"), $diffPatch, $utf8NoBom) + [System.IO.File]::WriteAllText([System.IO.Path]::Combine($tempDir, "REVIEW_CHANGED_FILES.txt"), $changedFilesText, $utf8NoBom) + + # Generate REVIEW_CONTEXT.md + $gitLogStat = (git log --stat "$baseSha..HEAD") -join "`n" + + $reviewContextLines = @( + "# Randomayzer Review Snapshot (Diff Mode)", + "", + "- **Full commit SHA:** $headSha", + "- **Short SHA:** $shortSha", + "- **Branch:** $branch", + "- **Generated at:** $timestamp", + "- **Repository:** $remoteUrl", + "- **Snapshot mode:** DIFF", + "- **Base commit:** $baseSha ($baseShortSha)", + "- **Target commit:** $headSha ($shortSha)", + "- **Working tree dirty at export time:** $dirtyText", + "", + "## Source of Truth", + "The files in this archive are the exact tracked repository snapshot for the commit shown above.", + "This archive contains the diff against base commit, changed files, relevant test suites, schema definitions, and project documentation.", + "", + "## Reviewer Instructions", + "Do not use GitHub HEAD as source of truth.", + "Review the attached snapshot.", + "- Check `REVIEW_DIFF.patch` for the complete patch.", + "- Check `REVIEW_CHANGED_FILES.txt` for the list of modified files.", + "- Inspect the included source and test files.", + "", + "## Recent Commit Log ($baseShortSha..$shortSha)", + '```', + $gitLogStat, + '```' + ) + $reviewContext = $reviewContextLines -join "`n" + + [System.IO.File]::WriteAllText([System.IO.Path]::Combine($tempDir, "REVIEW_CONTEXT.md"), $reviewContext, $utf8NoBom) + + # Compress staged directory + [System.IO.Compression.ZipFile]::CreateFromDirectory($tempDir, $zipFilePath, [System.IO.Compression.CompressionLevel]::Optimal, $false) + } finally { + if (Test-Path -LiteralPath $tempDir) { + Remove-Item -LiteralPath $tempDir -Recurse -Force -ErrorAction SilentlyContinue + } + } +} + +# 6. Verify Archive & Display Summary +$zip = [System.IO.Compression.ZipFile]::OpenRead($zipFilePath) +$fileCount = $zip.Entries.Count +$zip.Dispose() + +$fileInfo = Get-Item -LiteralPath $zipFilePath +$sizeBytes = $fileInfo.Length +$sizeFormatted = if ($sizeBytes -ge 1MB) { + "{0:N2} MB ({1:N0} bytes)" -f ($sizeBytes / 1MB), $sizeBytes +} elseif ($sizeBytes -ge 1KB) { + "{0:N2} KB ({1:N0} bytes)" -f ($sizeBytes / 1KB), $sizeBytes +} else { + "{0} bytes" -f $sizeBytes +} + +Write-Host "" +Write-Host "==================================================" -ForegroundColor Cyan +Write-Host " Randomayzer Review Package Exported Successfully " -ForegroundColor Cyan +Write-Host "==================================================" -ForegroundColor Cyan +Write-Host ("Created: " + $zipFilePath) -ForegroundColor Green +Write-Host ("Commit: " + $headSha + " (" + $shortSha + ")") +Write-Host ("Mode: " + $modeName) +Write-Host ("Files: " + $fileCount) +Write-Host ("Size: " + $sizeFormatted) +Write-Host "==================================================" -ForegroundColor Cyan + +# 7. Optional Clipboard Prompt +if ($CopyPrompt) { + $clipboardPromptLines = @( + "В приложенном архиве snapshot Randomayzer на commit $headSha.", + "Используй архив как source of truth.", + "Не используй GitHub HEAD вместо него.", + "Выполни ранее выданное security review задание." + ) + $clipboardPrompt = $clipboardPromptLines -join "`n" + + try { + if (Get-Command Set-Clipboard -ErrorAction SilentlyContinue) { + Set-Clipboard -Value $clipboardPrompt + Write-Host "Reviewer prompt copied to clipboard." -ForegroundColor Yellow + } else { + Write-Warning "Set-Clipboard is not available in this environment." + } + } catch { + Write-Warning "Could not copy prompt to clipboard: $_" + } +}