On this page
- Operational Workflows (Agentic)
- The Toolchain Trinity (Core Scripts)
- Architectural Patterns
- The Animation Sequence Protocol (Folder-to-WebP)
- Asset Pipeline
- Standard Operating Procedure: Lightroom Export (The Honda Standard)
- DXF Rendering Issues
- MDX Errors (Astro Content Layer)
- The Timeline Trap (Infinite Bubble)
- Broken Site Logos / Favorites
- Cloudflare Image Service Warning
- Cloudflare KV Binding Error (Static Build)
- IDE Tooling Errors (“Stream Error”)
- Asset & Schema Errors
- Hyperspace Migration (Batch Upgrade)
- The Orphan Trap (Data Stripping)
- The “Ghost Folder” 404 (Static Assets)
- Gallery Crashes (Relative URLs)
- Auditory/Visual Engine Maintenance
- Starfield Visibility (The “Black Curtain” Trap)
- Audio Protocol Leakage (Iron Dome Failure)
- Resume Infrastructure (PDF Pipeline)
Maintenance & Troubleshooting
System Maintenance & Troubleshooting
This document serves as the first line of defense for system issues, build failures, and pipeline errors.
Operational Workflows (Agentic)
These tasks are now automated via Slash Commands in the IDE.
- Runtime Rule: Agent-critical scripts must use explicit interpreters. Use
D:\GitHub\global_agent\venv\Scripts\python.exefor session-open/global-agent checks, and use the Codex bundled Python/Node underC:\Users\erik\.cache\codex-runtimes\codex-primary-runtime\dependencies\for sandboxed portfolio validation. - New Project:
/scaffold-project(Generates strict C24 Schema). - Deploy:
/deploy-production(Verify Build + Push to Main). - New Project:
/scaffold-project(Generates strict C24 Schema). - Deploy:
/deploy-production(Verify Build + Push to Main). - Hack Pack:
scripts/compile_hack_pack.py(GeneratesBOLUS+REPORT+PODCAST). - Master Resume:
assets.eriknorris.com/resume/Erik_Norris_Resume_Current.pdf(served from R2, not from the site — see Resume Infrastructure below).
The Toolchain Trinity (Core Scripts)
These scripts are the engine of the “Forensic Data Factory.”
Architectural Patterns
-
The Hybrid Scroll (Performance):
- Context: Heavy 3D scenes (R3F) cause main-thread lag if coupled with React State-driven scroll hooks (like
useScroll). - Pattern: Use Vanilla JS
scrolllisteners attached to specific containers (e.g.,#hyperspace-container) to calculate progress (0-1) and pass it into the Canvas via a single State update or Ref. - Benefit: Decouples the 60fps render loop from the scroll event loop.
- Context: Heavy 3D scenes (R3F) cause main-thread lag if coupled with React State-driven scroll hooks (like
-
Hydration Engine:
npm run content:hydrate- Source:
scripts/hydrate_content.py - Purpose: Injects NotebookLM “Bolus” data (JSON) into MDX Frontmatter (Metrics, Toolchains, Summaries).
- Behavior:
- Mines Stickies: Scans
R2_MASTERfor bubble assets. - Injects Intelligence: Auto-detects
{slug}.mdinnotebook_dumps/and copies it to_intelligence.mdfor Assembly metrics. - Updates Metadata: Syncs
forensic_metrics,toolchain, andpresentation_mode.
- Mines Stickies: Scans
- Source:
-
Schema Modernizer:
npm run content:modernize- Source:
scripts/modernize_content.py - Purpose: Mass-updates legacy content to the latest C24 Schema.
- Behavior: Injects default values for new fields (
cyberspace,metrics,statusLabel). Use for bulk refactors.
- Source:
-
Asset Refinery:
npm run assets:process- Source:
scripts/process_assets.py(formerlyprocess_images.py) - Purpose: The “Heavy Lifter” for media.
- Capabilities:
- Images: Resizes to standard breakpoints (xl, lg, md, sm) and generates WebP.
- Audio:
- Source:
R2_MASTER/[slug]/[filename].wav - Naming:
[slug]-briefing.wav(Standard) or[slug]-deep_dive.wav - Output:
R2_MIRROR/[slug]/[filename].mp3(192kbps) - Global Audio: Use
identityslug (e.g.,R2_MASTER/identity/identity-overview.wav).
- Source:
- Usage:
npm run assets:process(Process specific slugs in R2_MASTER).npm run assets:process -- --all(Re-process EVERYTHING).npm run assets:process -- [slug](Target specific project).
- Source:
The Animation Sequence Protocol (Folder-to-WebP)
Context: Used for “Stop Motion” style clips or frame-by-frame UI animations (like boot sequences).
- Trigger: Create a Folder inside a project or bubble (instead of a single image file).
- Folder Metrics:
- Syntax:
[sequence_name]-[duration]ms - Example:
boot_sequence-50ms(Each frame plays for 50ms). - Default: 2000ms if no suffix is provided.
- Syntax:
- Content:
- Place sequential images inside:
001.jpg,002.jpg, etc. - Sorting: Alphanumeric. Use leading zeros (
001, not1) to ensure correct order.
- Place sequential images inside:
- Output:
- Animated WebP:
[sequence_name]-[breakpoint].webp(The playable clip). - Frame Folder: Copies source frames to
[output]/[sequence_name]/for individual frame access (React components).
- Animated WebP:
Asset Pipeline
Standard Operating Procedure: Lightroom Export (The Honda Standard)
Rationale: The process_assets.py script is a “Lossy Downscaler.” It requires high-quality, high-resolution inputs (JPEGs) to generate optimized WebP outputs.
Export Settings (R2_MASTER):
- File Settings:
- Format:
JPEG(Quality 90-100). Do NOT use TIFF (Overkill) or JXL (Unsupported). - Color Space:
sRGB.
- Format:
- Image Sizing:
- Resize to Fit: Width & Height.
- W / H:
2500px. (Provides buffer for the1920pxXL breakpoint). - Resolution:
72ppi (Metadata only). - Legacy Assets: If original < 800px, use Super Resolution or Upscayl to target ~2500px BEFORE export.
- Output Sharpening:
- Sharpen For: Screen (Standard).
- Metadata:
- Copyright Only: Strip GPS/Camera info.
DXF Rendering Issues
-
Symptom:
ModuleNotFoundError: No module named 'ezdxf'ormatplotlib. -
Context: The DXF pipeline (“The Sidecar”) introduces heavy Python dependencies that are not part of the standard
requirements.txtcore set to keep the main build light. -
Fix:
Terminal window pip install -r scripts/requirements.txtNote: We recently added
ezdxfandmatplotlibtorequirements.txt(Jan 2026), so ensure your local environment is synced. -
Symptom:
[ERROR] Rendering failed: ... -
Fix:
- Verify the input file is a valid DXF (Try opening in a viewer like Autodesk TrueView or ODA Viewer).
- Check for “Text Style” missing fonts (matplotlib backend may fallback to default font, which is non-fatal but looks different).
- Run the sidecar in standalone mode to isolate the error:
Terminal window python scripts/lib/dxf_renderer.py "path/to/dxf/file.dxf"
MDX Errors (Astro Content Layer)
- Symptom:
MDXError: Unexpected character 0(or 1-9) preventing dev server startup. - Cause: The MDX parser interprets unquoted keys starting with numbers (e.g.,
01_intro:) as octal or invalid identifiers. It also flags<symbols followed by numbers in body text (e.g.,<0.5mm) as invalid JSX tags. - Fix:
- Frontmatter: Quote ALL keys/values starting with a number:
01_intro->"01_intro". - Body Text: Escape
<if followed by a number or currency:<0.5mm-><0.5mm.- Trap:
<$15k(interpreted as tag). FIX:<$15korless than $15k. - Trap:
<40%(interpreted as tag). FIX:less than 40%.
- Trap:
- Frontmatter: Quote ALL keys/values starting with a number:
The Timeline Trap (Infinite Bubble)
- Symptom: A project’s bubble in the Visualization is massively oversized (e.g., covering the whole screen).
- Cause: Missing End Date. If a project has
date(Start) but noendDateorduration, the visualization engine assumes it is still active (Duration = Start Date to Now -> 20+ Years). - Fix: Ensure every project has an
endDatein frontmatter.date: 2003-01-01endDate: 2004-05-01 # Cap the duration
Broken Site Logos / Favorites
- Symptom: “EN” Logo appears as a broken image icon or text alt-tag in Header/Footer.
- Cause: Missing or corrupt
EN_logo_1200.svginpublic/assets/branding/. - Fix: Restore the canonical “Fake SVGs” from the backup vault:
copy "d:\portfolio\portfolio_working\EN_logo\EN_15-based_good-reference-but _fake-SVGS____\*.svg" "public/assets/branding\" - Note: Do not use
Asset 2.svg(Wireframe); it is incorrect.
Cloudflare Image Service Warning
- Symptom:
[WARN] Cloudflare does not support sharp at runtime. However, you can configure imageService: "compile"... - Cause: The Cloudflare adapter detects Sharp is installed but unavailable in the Edge runtime.
- Fix: Explicitly configure the adapter to use Sharp during the build/compile phase only:
astro.config.mjs adapter: isProduction ? undefined : cloudflare({ imageService: "compile" }),
Cloudflare KV Binding Error (Static Build)
- Symptom: Build fails with
Invalid binding 'SESSION': binding not found in wrangler.toml. - Cause:
adapter: undefined(Static Mode) inastro.config.mjsdisables server-side sessions, butwrangler.tomlstill has a[[kv_namespaces]]binding forSESSION. - Fix: Remove the
[[kv_namespaces]]block fromwrangler.tomlwhen deploying a Static site.
IDE Tooling Errors (“Stream Error”)
- Symptom: “Error generating commit message: … stream error” or “404 models/gemini-1.5-flash not found”.
- Cause:
- Global IDE Outage: The Antigravity IDE has a known bug with the native “Generate” button failing to stream responses (Jan 2026).
- Billing Mismatch: “Google One Ultra” (Consumer) does NOT cover API usage. You must have a credit card on the specific Google Cloud Project for the API Key.
- Fix:
- Run Diagnostic:
python scripts/test_gemini_key.py. - If Script Works: The API Key is fine. The IDE is broken. Use Manual Commits.
- If Script Fails (429): Add billing to Google Cloud Console for the project.
- Run Diagnostic:
Asset & Schema Errors
-
Symptom:
ImageNotFound: Could not find requested image... -
Cause: A component is referencing a relative asset path that was deleted (e.g.,
web-reaper/avatar.jpg). -
Fix: Grep the
srcdirectory for the missing filename. It’s often in a “Tiny Image” component or legacy content. -
Symptom:
YAMLException: can not read an implicit mapping pair; a colon is missed -
Cause: A markdown line in frontmatter starts with
*. YAML interprets this as an alias anchor or list item. -
Fix: The Asterisk Law: You MUST quote any string starting with
*or special characters.narrative: "* The system failed..."->narrative: "* The system failed..."(Wait, quotes are required).narrative: "* The system"(Fails).narrative: "* The system"(Fixed:narrative: '* The system').
Hyperspace Migration (Batch Upgrade)
-
Script:
node scripts/migrate_to_hyperspace.js -
Usage:
--dry-run: Preview changes.--write: Apply changes (Back up first!).
-
Logic:
- Standardizes
theme: "hyperspace". - Promotes
metrics->deep_dive. - Renames
deck->legacy_deck.
- Standardizes
-
Symptom:
Error: Field validation failed: teamSize: Must be a string -
Cause: The Zod schema expects a String, but a Number was provided in the markdown frontmatter.
-
Fix: Quote the value in the
.mdxfile:teamSize: 6->teamSize: "6".
The Orphan Trap (Data Stripping)
- Symptom: Python Hydration script runs successfully (
✅ Updated: 1), but the data (toolchain,forensic_summary) does not appear in the Build. - Cause: Schema Collision. The field exists in the MDX file, but Astro’s Zod Schema (
content.config.ts) is in strict mode and silently strips fields it does not define. - Fix: The Schema Law:
- Define field in
src/content.config.ts(Build Safety). - Inject field via
hydrate_content.py(Automation).
- Define field in
The “Ghost Folder” 404 (Static Assets)
- Symptom: You add a folder to
public/(e.g.,public/digiME), butlocalhost:4321/digiME/returns a 404. - Cause:
- Astro Caching: The Dev Server does not always hot-reload structure changes in
public/. - Zombie Processes (Windows):
npm run devmight fail to close the port, leaving a stalenode.exerunning on 4321 while your new server runs on 4322. You are browsing the OLD server.
- Astro Caching: The Dev Server does not always hot-reload structure changes in
- Fix: Terminate with extreme prejudice.
Terminal window taskkill /F /IM node.exenpm run dev
Gallery Crashes (Relative URLs)
-
Symptom:
TypeError: Invalid URLcrashing the entire Gallery component. -
Cause: Using
new URL(image.href)on a relative internal link (e.g.,/legacy). The browserURLconstructor mandates an absolute URI schema. -
Fix:
// BADnew URL(image.href).hostname;// GOODtry {return new URL(image.href).hostname;} catch {return "INTERNAL"; // or handle relative path manually
Auditory/Visual Engine Maintenance
-
Symptom: Morphing animation (ECG -> Pulse) looks broken, “teleporting” or snapping lines.
-
Cause: Topology Mismatch. Framer Motion cannot smoothly interpolate between paths with different point counts or command types (e.g., converting a Curve
Cto a LineL). -
Fix: Normalize both paths to use the same number of Segment commands (
L).- ECG Path: 11 points (10 Line segments).
- Pulse Path: 11 points (10 Line segments).
- Do not use Bezier curves for the target shape if the source is polygonal.
-
Symptom: Active EQ Visualization looks like a “Techno Strobe” or glitchy.
-
Cause: Animation cadence is too fast (<0.4s) or uses
lineareasing. -
Fix: Tune to Iambic Pentameter.
- Duration: 0.6s - 1.0s.
- Ease:
easeInOut. - Noise: Inject randomized height variance (
Math.random()) so bars don’t move in unison.
Starfield Visibility (The “Black Curtain” Trap)
- Symptom: The Starfield is visible on Homepage but “Black” on Project Pages, or flashes black then appears.
- Cause:
- Hydration Latency:
client:idle(default) delays the R3F Canvas initialization until the main thread is free. On heavy project pages, this gap is visible as a black void. - Opaque Layers: Tailwind defaults like
bg-black/90on HUDs orbg-neutral-900on containers create overlapping “Curtains” that block the collimated background.
- Hydration Latency:
- Fix:
- Boost Hydration: Use
client:loadfor<CollimatedBackground />on[...slug].astro. - Enforce Stealth: Locate opaque containers (Review Assembly/Timeline divs) and set
bg-transparent.
- Boost Hydration: Use
Audio Protocol Leakage (Iron Dome Failure)
- Symptom: The Audio Host reads your prompts aloud (e.g., “System Instruction: You are a Forensic Architect…”).
- Cause: Contamination. You included “Instructional Headers” in a file visible to the Audio Model. The Audio Model treats ALL source text as “Script.”
- Fix:
- Purge: Remove
REFINE_READY.txtfrom the source list. - Decouple: Use
PODCAST_READY.txt(which has NO instruction headers) + The “Densified Report” (converted to Source). - Reset: You MUST start a new chat context. Once the model has “read” the bad prompt, it is poisoned.
- Purge: Remove
Resume Infrastructure (PDF Pipeline)
- Source of Truth:
src/config/resume_master.ts(Structured Content). - Generation (Headless):
node scripts/generate_resume_pdf.cjs(from the repo root). Spawns a headless Astro dev server on port 4321 and prints/resumevia Puppeteer with print-media emulation. Replaces the old interactive Browser Print -> Save-to-PDF flow.- Trap: The script exits 0 even when printing fails inside its try/catch. Verify the output PDF’s mtime on the filesystem; stdout success lines prove nothing.
- Output (R2_MIRROR, not
public/):- Current:
D:\GitHub\portfolio-assets\R2_MIRROR\resume\Erik_Norris_Resume_Current.pdf - Archive:
D:\GitHub\portfolio-assets\R2_MIRROR\resume\archive\Erik_Norris_Resume_[YYYY-MM-DD].pdf
- Current:
- Deploy:
venv/Scripts/python.exe scripts/sync_r2.py --target portfolio(fromD:\GitHub\global_agent). Additive sync ofR2_MIRROR-> R2 bucketassets-eriknorris-com. Size-matched files are skipped; nothing is pruned. RequireErrors: 0in the printed summary (the exit code lies); if the fresh PDF shows as Skipped, re-run with--force.- Retired:
scripts/fix_resume_r2.py(now inscripts/_archive/). Do not use it.
- Retired:
- Live URL:
https://assets.eriknorris.com/resume/Erik_Norris_Resume_Current.pdf. Verify withcurl -sI: require HTTP 200 and aContent-Lengthequal to the staging file’s byte size. - Legacy Vanity URL (
resume.eriknorris.com): 302s to the HTML pagehttps://eriknorris.com/resume(verified 2026-06-12), NOT to a PDF. Never use it to verify a deploy — checking the redirect instead of the asset is how a stale live PDF went unnoticed for ~3 months. - Orchestration: The
/update-resumeskill (global_agent/.agent/skills/update-resume/SKILL.md) runs the full sequence: synthesis -> LGTM gate -> generate -> deploy -> live byte-parity check.