Files
Mike Swanson 75ce1c2fd5 feat: Add Sequential Thinking to Code Review + Frontend Validation
Enhanced code review and frontend validation with intelligent triggers:

Code Review Agent Enhancement:
- Added Sequential Thinking MCP integration for complex issues
- Triggers on 2+ rejections or 3+ critical issues
- New escalation format with root cause analysis
- Comprehensive solution strategies with trade-off evaluation
- Educational feedback to break rejection cycles
- Files: .claude/agents/code-review.md (+308 lines)
- Docs: CODE_REVIEW_ST_ENHANCEMENT.md, CODE_REVIEW_ST_TESTING.md

Frontend Design Skill Enhancement:
- Automatic invocation for ANY UI change
- Comprehensive validation checklist (200+ checkpoints)
- 8 validation categories (visual, interactive, responsive, a11y, etc.)
- 3 validation levels (quick, standard, comprehensive)
- Integration with code review workflow
- Files: .claude/skills/frontend-design/SKILL.md (+120 lines)
- Docs: UI_VALIDATION_CHECKLIST.md (462 lines), AUTOMATIC_VALIDATION_ENHANCEMENT.md (587 lines)

Settings Optimization:
- Repaired .claude/settings.local.json (fixed m365 pattern)
- Reduced permissions from 49 to 33 (33% reduction)
- Removed duplicates, sorted alphabetically
- Created SETTINGS_PERMISSIONS.md documentation

Checkpoint Command Enhancement:
- Dual checkpoint system (git + database)
- Saves session context to API for cross-machine recall
- Includes git metadata in database context
- Files: .claude/commands/checkpoint.md (+139 lines)

Decision Rationale:
- Sequential Thinking MCP breaks rejection cycles by identifying root causes
- Automatic frontend validation catches UI issues before code review
- Dual checkpoints enable complete project memory across machines
- Settings optimization improves maintainability

Total: 1,200+ lines of documentation and enhancements

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-17 16:23:52 -07:00

105 lines
6.5 KiB
Plaintext

660→ }
661→
662→ function renderMachinesList() {
663→ const container = document.getElementById("machinesList");
664→
665→ if (machines.length === 0) {
666→ container.innerHTML = '<div class="empty-state"><h3>No machines</h3><p>Install the agent on a machine to see it here</p></div>';
667→ return;
668→ }
669→
670→ container.innerHTML = '<div style="padding: 12px;">' + machines.map(m => {
671→ const started = new Date(m.started_at).toLocaleString();
672→ const isSelected = selectedMachine?.id === m.id;
673→ return '<div class="sidebar-item' + (isSelected ? ' active' : '') + '" onclick="selectMachine(\'' + m.id + '\')" style="margin-bottom: 8px; padding: 12px;">' +
674→ '<div style="display: flex; align-items: center; gap: 12px;">' +
675→ '<div style="width: 10px; height: 10px; border-radius: 50%; background: hsl(142, 76%, 50%);"></div>' +
676→ '<div>' +
677→ '<div style="font-weight: 500;">' + (m.agent_name || m.agent_id.slice(0,8)) + '</div>' +
678→ '<div style="font-size: 12px; color: hsl(var(--muted-foreground));">Connected ' + started + '</div>' +
679→ '</div>' +
680→ '</div>' +
681→ '</div>';
682→ }).join("") + '</div>';
683→ }
684→
685→ function selectMachine(id) {
686→ selectedMachine = machines.find(m => m.id === id);
687→ renderMachinesList();
688→ renderMachineDetail();
689→ }
690→
691→ function renderMachineDetail() {
692→ const container = document.getElementById("machineDetail");
693→
694→ if (!selectedMachine) {
695→ container.innerHTML = '<div class="empty-state"><h3>Select a machine</h3><p>Click a machine to view details</p></div>';
696→ return;
697→ }
698→
699→ const m = selectedMachine;
700→ const started = new Date(m.started_at).toLocaleString();
701→
702→ container.innerHTML =
703→ '<div class="detail-section">' +
704→ '<div class="detail-section-title">Machine Info</div>' +
705→ '<div class="detail-row"><span class="detail-label">Agent ID</span><span class="detail-value">' + m.agent_id.slice(0,8) + '...</span></div>' +
706→ '<div class="detail-row"><span class="detail-label">Session ID</span><span class="detail-value">' + m.id.slice(0,8) + '...</span></div>' +
707→ '<div class="detail-row"><span class="detail-label">Connected</span><span class="detail-value">' + started + '</span></div>' +
708→ '<div class="detail-row"><span class="detail-label">Viewers</span><span class="detail-value">' + m.viewer_count + '</span></div>' +
709→ '</div>' +
710→ '<div class="detail-section">' +
711→ '<div class="detail-section-title">Actions</div>' +
712→ '<button class="btn btn-primary" style="width: 100%; margin-bottom: 8px;" onclick="connectToMachine(\'' + m.id + '\')">Connect</button>' +
713→ '<button class="btn btn-outline" style="width: 100%; margin-bottom: 8px;" onclick="openChat(\'' + m.id + '\', \'' + (m.agent_name || 'Client').replace(/'/g, "\\'") + '\')">Chat</button>' +
714→ '<button class="btn btn-outline" style="width: 100%; margin-bottom: 8px;" disabled>Transfer Files</button>' +
715→ '<button class="btn btn-outline" style="width: 100%; color: hsl(0, 62.8%, 50%);" onclick="disconnectMachine(\'' + m.id + '\', \'' + (m.agent_name || m.agent_id).replace(/'/g, "\\'") + '\')">Disconnect</button>' +
716→ '</div>';
717→ }
718→
719→ function connectToMachine(sessionId) {
720→ // Open viewer in new window
721→ const viewerUrl = "/viewer.html?session_id=" + sessionId;
722→ window.open(viewerUrl, "viewer_" + sessionId, "width=1280,height=800,menubar=no,toolbar=no,location=no,status=no");
723→ }
724→
725→ async function disconnectMachine(sessionId, machineName) {
726→ if (!confirm("Disconnect " + machineName + "?\\n\\nThis will end the remote session.")) return;
727→ try {
728→ const response = await fetch("/api/sessions/" + sessionId, { method: "DELETE" });
729→ if (response.ok) {
730→ selectedMachine = null;
731→ renderMachineDetail();
732→ loadMachines();
733→ } else {
734→ alert("Failed to disconnect: " + await response.text());
735→ }
736→ } catch (err) {
737→ alert("Error disconnecting machine");
738→ }
739→ }
740→
741→ // Refresh machines every 5 seconds
742→ loadMachines();
743→ setInterval(loadMachines, 5000);
744→
745→ // ========== Chat Functions ==========
746→
747→ // Chat modal elements
748→ const chatModal = document.getElementById("chatModal");
749→ const chatMessagesEl = document.getElementById("chatMessages");
750→ const chatInput = document.getElementById("chatInput");
751→ const chatSend = document.getElementById("chatSend");
752→ const chatClose = document.getElementById("chatClose");
753→ const chatClientName = document.getElementById("chatClientName");
754→
755→ // Close chat modal
756→ chatClose.addEventListener("click", () => {
757→ closeChat();
758→ });
759→
<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>