import axios from 'axios'; import chalk from 'chalk'; import { generateContextHashes, detectDrift } from './hasher.js'; import path from 'path'; /** * Syncs the local state with Nexus Registry. * Handles "Digital Sealing" and architecture verification. */ export async function syncNexus(apiUrl: string, apiKey: string, projectId: string, cwd: string, force: boolean = false) { console.log(chalk.bold('\n🏛️ Nexus Registry Synchronization...')); try { // 1. Check if baseline already exists if (!force) { const existing = await axios.get(`${apiUrl}/api/v1/nexus/decisions`, { params: { project_id: projectId, slug: 'current-baseline' }, headers: { Authorization: `Bearer ${apiKey}` } }); if (existing.data.success && existing.data.decision) { console.log(chalk.dim(' Existing baseline found in Nexus Registry. Skip sealing...')); return { success: true, hashes: existing.data.decision.context_hashes }; } } // 2. Generate Signatures const patterns = [ 'IMPLEMENTATION_PLAN.md', 'IMPLEMENTATION_PLAN_*.md', 'apps/web/src/actions/brain.ts', 'apps/web/src/components/dashboard/project-brain-panel.tsx', 'apps/web/src/components/onboarding/workshop-page.tsx', 'apps/web/src/lib/brain/**/*.ts', 'packages/cli/src/**/*.ts' ]; const hashes = await generateContextHashes(cwd, patterns); const fileCount = Object.keys(hashes).length; console.log(chalk.dim(` Generated ${fileCount} signatures for core modules.`)); // 3. Digital Sealing: Upload to Nexus Registry const response = await axios.post(`${apiUrl}/api/v1/nexus/seal`, { project_id: projectId, hashes, title: `Boot Sync baseline`, slug: 'current-baseline', rationale: 'Automated baseline from CLI boot-up.' }, { headers: { Authorization: `Bearer ${apiKey}` } }); if (response.data.success) { console.log(chalk.green(` ✅ Digital Seal applied. State is now ACCEPTED baseline.`)); } return { success: true, hashes }; } catch (error: any) { console.warn(chalk.yellow(` ⚠ Nexus Sync failed: ${error.message}`)); return { success: false, error: error.message }; } } /** * Verifies local code against the "Contract" in Nexus. */ export async function checkArchitectureDrift(apiUrl: string, apiKey: string, projectId: string, cwd: string) { try { // 1. Fetch baseline from Nexus // Normally we'd have a GET endpoint for this // For now, we'll simulate fetching the 'current-baseline' const response = await axios.get(`${apiUrl}/api/v1/nexus/decisions`, { params: { project_id: projectId, slug: 'current-baseline' }, headers: { Authorization: `Bearer ${apiKey}` } }); if (!response.data.success || !response.data.decision) return; const baselineHashes = response.data.decision.context_hashes || {}; // 2. Compare with current const currentHashes = await generateContextHashes(cwd, Object.keys(baselineHashes)); const drift = detectDrift(currentHashes, baselineHashes); if (drift.length > 0) { console.log(chalk.bold('\n🛡️ Architecture Drift Detected:')); drift.forEach(d => { const color = d.type === 'MODIFIED' ? chalk.yellow : chalk.red; console.log(color(` ${d.type.padEnd(8)}: ${d.file}`)); }); console.log(chalk.dim(' (Run "rigstate heal" or "rigstate sync" to update baseline)')); } else { console.log(chalk.green('\n✅ Architecture Integrity: Verified. Local matches baseline.')); } } catch (e) { // Skip silently if baseline not found } }