mirror of
https://github.com/bybrooklyn/alchemist.git
synced 2026-04-18 01:43:34 -04:00
push to v0.2.5-rc.1
This commit is contained in:
23
CHANGELOG.md
Normal file
23
CHANGELOG.md
Normal 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
2
Cargo.lock
generated
@@ -26,7 +26,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alchemist"
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argon2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "alchemist"
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
edition = "2021"
|
||||
license = "GPL-3.0"
|
||||
|
||||
|
||||
@@ -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*
|
||||
|
||||
4
migrations/20260111193000_update_version_to_0_2_5.sql
Normal file
4
migrations/20260111193000_update_version_to_0_2_5.sql
Normal 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'));
|
||||
@@ -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
4632
web/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "alchemist-web",
|
||||
"version": "0.2.4",
|
||||
"version": "0.2.5",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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()}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user