feat: Add Linux deployment scripts and server logs view

- Add deployment/linux/ with deploy.sh for deploying from Claude-Agent LXC to Windows server
- Add ServerLogsView.vue for viewing server logs from frontend
- Add shared/routes/system.py for system health endpoints
- Update CLAUDE.md with quick deploy instructions
- Improve Windows deployment scripts (ROA2WEB-Console.ps1)
- Fix OCR service validation and worker pool improvements
- Update environment config examples
- Various script permission and startup fixes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-01-04 00:26:36 +00:00
parent 495790411f
commit 02a8c8682c
39 changed files with 1939 additions and 80 deletions

View File

@@ -75,9 +75,10 @@ class OCRWorkerPool:
self._sync_lock = mp.Lock()
# Register cleanup handlers
# NOTE: Only use atexit, NOT signal handlers!
# Signal handlers interfere with FastAPI's shutdown handling.
# FastAPI's shutdown event calls stop_job_worker() which calls shutdown().
atexit.register(self._cleanup_on_exit)
signal.signal(signal.SIGTERM, self._signal_handler)
signal.signal(signal.SIGINT, self._signal_handler)
self._initialized = True
logger.info("[OCRWorkerPool] Singleton instance created")

View File

@@ -1004,7 +1004,7 @@ class OCRValidationEngine:
for replacement in candidates + all_digits:
candidate = cui_digits[:pos] + replacement + cui_digits[pos+1:]
if CUIChecksumRule.validate_checksum(candidate):
print(f"[CUI Repair] Fixed {cui_digits} {candidate} (position {pos}: {original_digit}{replacement})", flush=True)
print(f"[CUI Repair] Fixed {cui_digits} -> {candidate} (position {pos}: {original_digit}->{replacement})", flush=True)
return candidate
# No single-digit fix found
@@ -1164,7 +1164,7 @@ class OCRValidationEngine:
if CUIChecksumRule.validate_checksum(cui_digits):
match = await lookup_cui_in_db(cui_digits)
if match:
print(f"[Fuzzy CUI] Exact match found: {cui} {match[0]} ({match[1]})", flush=True)
print(f"[Fuzzy CUI] Exact match found: {cui} -> {match[0]} ({match[1]})", flush=True)
return match
# Valid checksum but not in DB - return as-is (it might be a new supplier)
return None
@@ -1214,7 +1214,7 @@ class OCRValidationEngine:
# Check if this corrected CUI exists in database
match = await lookup_cui_in_db(candidate)
if match:
print(f"[Fuzzy CUI] DB match: {cui} {match[0]} ({match[1]}) [pos {pos}: {original_digit}{replacement}]", flush=True)
print(f"[Fuzzy CUI] DB match: {cui} -> {match[0]} ({match[1]}) [pos {pos}: {original_digit}->{replacement}]", flush=True)
return match
# No match found in database
@@ -1269,7 +1269,7 @@ class OCRValidationEngine:
if not name_words:
return None
print(f"[Fuzzy Name] Searching for vendor: '{vendor_name}' keywords: {name_words}", flush=True)
print(f"[Fuzzy Name] Searching for vendor: '{vendor_name}' -> keywords: {name_words}", flush=True)
# Build search pattern - use first significant word
primary_word = name_words[0]