push to v0.2.5-rc.1

This commit is contained in:
brooklyn
2026-01-10 21:13:37 -05:00
parent 65d47035bf
commit 61630ce884
11 changed files with 4717 additions and 48 deletions

23
CHANGELOG.md Normal file
View File

@@ -0,0 +1,23 @@
# Changelog
All notable changes to this project will be documented in this file.
## [v0.2.5] - 2026-01-11
### 🛠 Fixes
- **Dashboard Crash**: Fixed a critical bug where the dashboard would render as a blank screen if GPU utilization was `null`. Added strict null checks before `toFixed()` calls in `ResourceMonitor.tsx`.
- **Animation Glitch**: Resolved an issue where the "Engine Status" button would fly in from the top-left corner on page navigation. Implemented unique `layoutId` generation using `useId()` to maintain the morph animation while preventing cross-page artifacts.
- **Migration Checksum**: Fixed a startup error caused by a modified migration file. Reverted the original migration to restore checksum integrity and created a new migration for the version bump.
### ⚡️ Improvements
- **Resource Monitor Layout**: Repositioned the GPU Usage section to appear between "Active Jobs" and "Uptime" for better logical flow.
- **Animation Timing**: Adjusted staggered animation delays in the Resource Monitor to match the new layout order.
### 📚 Documentation
- **Codebase Overview**: Added `codebase_overview.md` explaining the monolith architecture (Rust + API + Frontend) and directory structure.
- **Migration Policy**: Updated `MIGRATIONS.md` to explicitly forbid modifying existing migration files to prevent checksum errors.
- **Walkthrough**: Updated `walkthrough.md` with detailed debugging logs and verification steps for all recent changes.
### 🏗 Infrastructure
- **Version Bump**: Updated project version to `0.2.5` in `Cargo.toml`, `web/package.json`, and `VERSION`.
- **Database**: Established `0.2.5` as the new minimum compatible version schema baseline.

2
Cargo.lock generated
View File

@@ -26,7 +26,7 @@ dependencies = [
[[package]]
name = "alchemist"
version = "0.2.4"
version = "0.2.5"
dependencies = [
"anyhow",
"argon2",

View File

@@ -1,6 +1,6 @@
[package]
name = "alchemist"
version = "0.2.4"
version = "0.2.5"
edition = "2021"
license = "GPL-3.0"

View File

@@ -1 +1 @@
0.2.4
0.2.5

View File

@@ -613,9 +613,9 @@ Alchemist uses SQLite for persistence. The database file is located at `data/alc
## Database Migration Policy
> **Baseline Version: 0.2.4**
> **Baseline Version: 0.2.5**
All database migrations maintain **backwards compatibility** with the v0.2.4 schema. This means:
All database migrations maintain **backwards compatibility** with the v0.2.5 schema. This means:
- ✅ Newer app versions work with older database files
- ✅ Database files can be safely upgraded
@@ -642,7 +642,7 @@ The `schema_info` table tracks compatibility:
```sql
SELECT value FROM schema_info WHERE key = 'min_compatible_version';
-- Returns: "0.2.4"
-- Returns: "0.2.5"
```
---
@@ -733,7 +733,7 @@ volumes:
| Tag | Description |
|-----|-------------|
| `latest` | Latest stable release |
| `0.2.4` | Specific version |
| `0.2.5` | Specific version |
| `0.2` | Latest patch of minor version |
---
@@ -933,7 +933,7 @@ Version is tracked in two places that must stay in sync:
To release:
1. Update both files to new version
2. Commit: `git commit -m "v0.2.4: Description"`
2. Commit: `git commit -m "v0.2.5: Description"`
3. Push to master (triggers Docker build)
---
@@ -1182,7 +1182,7 @@ A:
## Changelog
### v0.2.4 (Current)
### v0.2.5 (Current)
- Async runtime reliability improvements (spawn_blocking for ffprobe/VMAF/hardware detection)
- Accurate encode_speed and avg_bitrate_kbps metrics computed from actual media duration
- GPU utilization monitoring in dashboard
@@ -1239,4 +1239,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
---
*Documentation for Alchemist v0.2.4+ • Last updated: January 2026*
*Documentation for Alchemist v0.2.5+ • Last updated: January 2026*

View File

@@ -0,0 +1,4 @@
-- Migration to update minimum compatible version to 0.2.5
INSERT OR REPLACE INTO schema_info (key, value) VALUES
('min_compatible_version', '0.2.5'),
('last_updated', datetime('now'));

View File

@@ -1,8 +1,8 @@
# Database Migration Policy
**Baseline Version: 0.2.4**
**Baseline Version: 0.2.5**
All database migrations from this point forward MUST maintain backwards compatibility with the v0.2.4 schema.
All database migrations from this point forward MUST maintain backwards compatibility with the v0.2.5 schema.
## Rules for Future Migrations
@@ -18,6 +18,7 @@ All database migrations from this point forward MUST maintain backwards compatib
- **Never change column types** - Add a new column instead
- **Never remove tables** - Mark as deprecated in comments instead
- **Never add NOT NULL columns without defaults**
- **Never modify existing migration files** - Once a migration is applied, it is immutable. Changing it breaks database integrity checksums. Creates a NEW migration file for any changes.
## Schema Version Tracking
@@ -36,7 +37,7 @@ Example: `20260109210000_add_notifications_table.sql`
## Testing Migrations
Before releasing any migration:
1. Test upgrading from v0.2.4 database
1. Test upgrading from v0.2.5 database
2. Verify all existing queries still work
3. Verify new features work with fresh DB
4. Verify new features gracefully handle missing data in old DBs

4632
web/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "alchemist-web",
"version": "0.2.4",
"version": "0.2.5",
"private": true,
"type": "module",
"scripts": {

View File

@@ -179,11 +179,48 @@ export default function ResourceMonitor() {
</div>
</motion.div>
{/* Uptime */}
{/* GPU Usage */}
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
className="p-4 rounded-2xl bg-white/5 border border-white/10 backdrop-blur-md"
>
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2 text-white/60 text-sm font-medium">
<Cpu size={16} /> GPU
</div>
{stats.gpu_utilization != null ? (
<span className={`text-xs font-bold px-2 py-0.5 rounded-full ${getUsageColor(stats.gpu_utilization)}`}>
{stats.gpu_utilization.toFixed(1)}%
</span>
) : (
<span className="text-xs font-bold px-2 py-0.5 rounded-full bg-white/10 text-white/40">
N/A
</span>
)}
</div>
<div className="space-y-1">
<div className="h-2 w-full bg-white/10 rounded-full overflow-hidden">
{stats.gpu_utilization != null && (
<div
className={`h-full rounded-full transition-all duration-500 ${getBarColor(stats.gpu_utilization)}`}
style={{ width: `${Math.min(stats.gpu_utilization, 100)}%` }}
/>
)}
</div>
<div className="flex justify-between text-xs text-white/40">
<span>VRAM</span>
<span>{stats.gpu_memory_percent?.toFixed(0) || "-"}% used</span>
</div>
</div>
</motion.div>
{/* Uptime */}
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 }}
className="p-4 rounded-2xl bg-white/5 border border-white/10 backdrop-blur-md flex flex-col justify-between"
>
<div className="flex items-center justify-between">
@@ -197,36 +234,7 @@ export default function ResourceMonitor() {
</div>
</motion.div>
{/* GPU Usage (only shown when GPU data available) */}
{stats.gpu_utilization !== undefined && (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 }}
className="p-4 rounded-2xl bg-white/5 border border-white/10 backdrop-blur-md"
>
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2 text-white/60 text-sm font-medium">
<Cpu size={16} /> GPU
</div>
<span className={`text-xs font-bold px-2 py-0.5 rounded-full ${getUsageColor(stats.gpu_utilization)}`}>
{stats.gpu_utilization.toFixed(1)}%
</span>
</div>
<div className="space-y-1">
<div className="h-2 w-full bg-white/10 rounded-full overflow-hidden">
<div
className={`h-full rounded-full transition-all duration-500 ${getBarColor(stats.gpu_utilization)}`}
style={{ width: `${Math.min(stats.gpu_utilization, 100)}%` }}
/>
</div>
<div className="flex justify-between text-xs text-white/40">
<span>VRAM</span>
<span>{stats.gpu_memory_percent?.toFixed(0) || 0}% used</span>
</div>
</div>
</motion.div>
)}
</div>
);
}

View File

@@ -1,4 +1,4 @@
import { useState, useEffect } from "react";
import { useState, useEffect, useId } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Activity, X, Zap, CheckCircle2, AlertTriangle, Database } from "lucide-react";
import { clsx, type ClassValue } from "clsx";
@@ -21,6 +21,7 @@ export default function SystemStatus() {
const [stats, setStats] = useState<Stats | null>(null);
const [isExpanded, setIsExpanded] = useState(false);
const [error, setError] = useState<string | null>(null);
const layoutId = useId();
useEffect(() => {
const fetchStats = async () => {
@@ -69,7 +70,7 @@ export default function SystemStatus() {
<>
{/* Compact Sidebar View */}
<motion.div
layoutId="status-container"
layoutId={layoutId}
onClick={() => setIsExpanded(true)}
className="flex flex-col gap-3 cursor-pointer group p-4 rounded-xl bg-helios-surface-soft border border-helios-line/40 shadow-sm"
whileHover={{ scale: 1.02 }}
@@ -127,7 +128,7 @@ export default function SystemStatus() {
>
{/* Modal Card */}
<motion.div
layoutId="status-container"
layoutId={layoutId}
className="w-full max-w-lg bg-helios-surface border border-helios-line/30 rounded-3xl shadow-2xl overflow-hidden relative"
onClick={(e) => e.stopPropagation()}
>