AI 资讯
从"玩具"到"教材":一个500行AI框架的自我修养
为什么我要造一个500行的Agent轮子? 你好,我是 FROST 的作者。 2026年了,Agent 框架多得能让人挑花眼:LangGraph 有 34.5M 月下载量,Dify 在 GitHub 斩获 129.8K Stars,各大厂商都在疯狂推自己的 SDK。这种环境下,再写一个"轮子",是不是有点多余? 说实话,我也纠结了很久。 一个困惑:新学者的两难困境 事情要从一次失败的辅导说起。 我帮一个朋友入门 Agent 开发,推荐了 LangChain。结果他学了两个月,还在和 chain.invoke() 搏斗,脑子里依然没有"Agent 到底是怎么工作的"这个概念。 问题出在哪? 现在的框架太强了,强到把所有的复杂性都藏了起来。 你可以三行代码跑起来一个 Agent,但你也永远不知道它内部发生了什么。就像学开车,你学会了踩油门转弯,但发动机是怎么工作的、变速箱怎么换挡,一概不知。 而对于想真正理解 Agent 本质的人来说,这是一个巨大的 Gap: 需求 现有选项 快速开发产品 LangChain/CrewAI 理解底层原理 论文 + 源码 入门级教学框架 ❌ 空白 这个空白,就是 FROST 存在的原因。 FROST 的设计哲学:Less is More FROST 不是一个生产级框架,它是一个 教学框架 。 这意味着它刻意放弃了: ❌ 复杂的依赖生态(不需要 LangChain) ❌ 丰富的工具集成(没有 100+ 内置工具) ❌ 分布式部署能力(就是单机 Python) 它只保留了三个核心概念: \ `python Store - 记忆容器(类似神经细胞的存储功能) class Store: """存储上下文、记忆、状态""" def init (self): self.data = {} Skill - 纯函数变换(类似神经细胞的处理功能) class Skill: """输入→处理→输出,无状态""" def call (self, store, *args, **kwargs): pass Agent - 执行单元(类似神经细胞本身) class Agent: """调用 Skill,操作 Store,完成目标""" def init (self, skills: list[Skill], store: Store): pass ` \ 是的,就这么简单。 三个类,不超过 500 行代码。 但正是这种简单,让"理解"变得可能。 一行代码跑起来的 Agent \ `python from frost import Agent, Store, Skill 定义一个"搜索助手"技能 class SearchSkill(Skill): def call (self, store, query): result = web_search(query) # 这里是你的搜索实现 store.set("last_search", result) return result 创建 Agent 并运行 store = Store() agent = Agent(skills=[SearchSkill()], store=store) response = agent.run("北京今天天气怎么样") print(response) ` \ 对比一下用 LangChain 实现同样的功能: \ `python from langchain.agents import AgentExecutor, create_react_agent from langchain_openai import ChatOpenAI ... 还有十几行初始化代码 ` \ FROST 让你从第一行代码开始,就知道自己在做什么: Agent 是执行者 Skill 是它的能力 Store 是它的记忆 没有魔法,没有黑箱,只有清晰的数据流。 为什么叫 FROST? FROST 的全称是 Fractal Remote Organ of Scalable Thoughts ——可扩展思维的分形远程器官。 这个名字源于它的设计灵感: 神经细胞(Neural Cell) 。 在生物学中,每个神经细胞都很简单: 接收信号 处理信号 发出信号 但当 亿万个神经细胞 连接在一起,就涌现出了智能。 FROST 试图在软件层面复现这个过程: Neural Cell → Agent Synapse → Skill Long-term Memory → Store Brain (Emergence) → Multi-Agent System 这不是在模仿大脑,而是在学习生物界的智慧: 简单单元 + 清晰连接 = 复杂行为。 我的踩坑日记 作为一个从零开始写框架的人,踩的坑比代码行
AI 资讯
"It’s just HTML and CSS. It’s too simple to post."
For a long time, I hesitated to share my work. I kept telling myself: "If I post a simple hero section, a basic Bootstrap grid, or a landing page clone, people will judge me. They’ll think I’m not a 'real' developer yet." But today, I saw a video of a developer who built a complete Netflix clone using only HTML & CSS in just 4 hours https://x.com/Aditwariii/status/1681403710457643009?s=20 . It made me stop and think. It’s easy to get so obsessed with complex frameworks, cloud architectures, and database optimizations that we begin to look down on the fundamentals. But here is the psychology of software engineering that we often ignore: Every master was once a beginner: The engineers managing complex distributed systems today started exactly where we are—struggling to center a div and fighting with CSS media queries. Shipping beats hiding: Building a clean, responsive interface in 4 hours shows speed, focus, and attention to detail. Those are core professional hygiene habits. Code is for humans, not just machines: Before we write APIs or database queries, we must master how a human being actually interacts with our interface. I’m letting go of the fear of being judged for "simple" things. From now on, I am building in public. Whether it’s a massive full-stack application or just a beautifully aligned hero section, it is proof of active practice and continuous momentum. Massive respect to [ https://x.com/Aditwariii?s=20 Check out Aditya Tiwari on X. POLYMATH 🧑💻 sde @IEX_INDIA_ ] for the inspiration and the reminder to keep shipping! 👇 What is a "small" project or layout you built recently that taught you a major lesson? Let's connect in the comments.
AI 资讯
Building a Local-First Voice Copilot for the Shell with HoldSpeak and Ollama
The Promise: A Private, Voice-Activated Shell The dream of a voice-activated command line is compelling: speak a command, see it executed. But for many developers, piping terminal input through a cloud-based API is a non-starter. This is the promise of a project like karolswdev/HoldSpeak , a cross-platform tool for local voice typing. Could it be the core of a truly local-first, push-to-talk shell assistant? I paired it with Ollama and a local llama3.2 model to find out. The goal was simple: hold a key, speak a command like "list files by size," release the key, and have the correct shell command appear, gated by a final confirmation prompt. This project turned out to be a tale of two stacks: one for voice that was surprisingly clean, and one for language that revealed the sharp edges of the local-first promise. Building the Demo To test this idea, I built a small Python script to tie these components together. You can find the complete code for this experiment, including the prompt engineering, in my demo project on GitHub: voice-activated-shell-demo . Setup Instructions Recreating this local-first voice assistant involves a few distinct steps: Install HoldSpeak from Source : Since we need to use it as a library, clone the repository and install it in editable mode. git clone https://github.com/karolswdev/HoldSpeak.git cd HoldSpeak pip3 install -e . Install and Run Ollama : Use Homebrew (on macOS) to install the Ollama CLI, then start the server. brew install ollama ollama serve Pull a Local LLM : In a separate terminal, pull a small, capable model. I used llama3.2 . ollama pull llama3.2 Grant Permissions (macOS) : To allow the hotkey listener to work, your terminal application (e.g., iTerm, Terminal.app) must be given Accessibility permissions in System Settings > Privacy & Security > Accessibility . Run the Demo Script : With the setup complete, you can run the final Python script that integrates all these components. Finding the Seams in HoldSpeak HoldSpeak pres
AI 资讯
Parsing and Rebuilding EPUB Files in Python: Lessons Learned
How we handle complex EPUB structures for AI translation without breaking navigation and metadata At LectuLibre , we built an AI‑powered book translation service. Users upload an EPUB, and our pipeline translates the text using LLMs like Claude and DeepSeek. That sounds straightforward until you have to parse and rebuild a valid EPUB without mangling the table of contents, internal links, or styles. I’m sharing the real‑world challenge we faced, how we chose our tooling, and the ugly corners we discovered when dealing with real‑world EPUB files. The Problem: EPUB is a Messy Zip File An EPUB is essentially a ZIP archive containing XHTML, CSS, images, and an OPF manifest. It’s a well‑defined standard (EPUB 3.2), but in practice publishers produce files that bend the rules: missing container.xml , inline styles that break after translation, and structural quirks that make parsing fragile. Our translation process needed to: Accept any EPUB the user throws at us. Extract all text content while preserving the exact structure. Send each paragraph to an LLM for translation. Re‑insert the translated text into the original XHTML files. Repackage everything into a new, valid EPUB. Step 4 is the tricky part: the translated text can be longer or shorter, it may contain characters that need escaping, and the surrounding markup must remain intact. Our Approach: Use ebooklib with a Dose of Defensive Coding We evaluated several Python libraries: epub (pypub) – too simple, no editing support. lxml + manual zip – too much boilerplate. ebooklib – full read/write with a clean API. We went with ebooklib . It provides an object‑oriented model of the EPUB structure, allows us to iterate over documents, and can write a new EPUB from the modified objects. The downside: its documentation is sparse and it can choke on malformed files. We had to layer on a lot of validation. Step 1: Loading and Validating the EPUB import ebooklib from ebooklib import epub def load_epub ( epub_path : str ) -> ep
开发者
I should I start cyber security from scratch I am new in this field I more curious about how this work I some know of programming languages like C, python
开发者
Trump Admin releases Anthropic Mythos to be used by more than 100 US companies, agencies
Over 100 companies and government agencies are reportedly authorized to use Mythos 5, including their non-American employees.
AI 资讯
Why Enterprise AI Needs Structured Dissent, Not Just More Agents
Many AI projects today are presented as multi-agent systems. One agent investigates. Another agent analyzes risk. A third agent checks compliance. A fourth agent gives a recommendation. It sounds advanced. But in a bank, adding more agents does not automatically make a workflow safe. A bank cannot freeze a customer account, block a payment, file a regulatory report, or label a transaction as fraud simply because an AI system produced a confident answer. The real question is not: How many AI agents are involved? The real question is: Can the system show evidence, challenge its own conclusion, apply deterministic rules, and stop for human approval when the decision is high impact? That is the difference between an interesting multi-agent demo and an enterprise-ready AI workflow. A banking example: suspicious wire transfer Imagine a bank detects a wire transfer for $250,000. The payment is unusual because: The customer has never sent a transfer of this size. The destination account is in a new country. The transaction happens outside the customer’s normal business hours. The beneficiary was added only a few minutes before the transfer. The customer recently changed their phone number and email address. A simple AI chatbot might say: “This transaction looks suspicious. Consider blocking it.” That is not enough. A bank needs to know: Which transaction patterns triggered the concern? Is the customer actually violating a known risk threshold? Is there a sanctions or AML issue? Could this be a legitimate business payment? What policy applies? Should the payment be blocked, held, or released? Who is allowed to make that decision? Can the bank explain the decision later to auditors, compliance teams, and the customer? This is where structured multi-agent design matters. A better design: a banking fraud decision room Instead of letting one model make a decision, the bank can create a controlled workflow with specialized agents. Transaction Alert ↓ Fraud Detection Agent ↓ Custo
产品设计
Swift Structs — Building Your Own Custom Types 🏗️
So far we've been working with Swift's built-in types — String, Int, Bool, Array. But what if you...
AI 资讯
Mastering the "Quantified Self": Building a Blazing-Fast Heart Rate Dashboard with DuckDB and Streamlit
As programmers, we love data. We track our commits, our uptime, and our deployment frequencies. But what about our most important "server"—our heart? 💓 The "Quantified Self" movement has led to an explosion of wearable data. However, if you've ever tried to analyze raw heart rate CSVs (often sampled every few seconds), you'll quickly realize that standard relational databases or even pure Pandas can get sluggish once you hit that 100k+ row mark. In this tutorial, we are going to build a high-performance Quantified Self Dashboard . We will leverage DuckDB —the "SQLite for Analytics"—to perform vectorized execution on heart rate data, paired with Streamlit and Plotly for a slick, interactive frontend. We’ll focus on Python data engineering , time-series analysis , and fast SQL processing . Why DuckDB? 🦆 Traditional databases are row-based, which is great for transactions but terrible for analytical queries. DuckDB is a columnar-vectorized query engine . This means it processes data in chunks (vectors) and utilizes modern CPU instructions (SIMD) to crunch numbers at speeds that make standard Python loops look like they're standing still. The Architecture Here is how our data pipeline flows from raw pixels (well, raw CSV rows) to actionable insights: graph TD A[Raw Heart Rate CSVs] -->|Direct Ingestion| B(DuckDB Engine) B -->|Vectorized SQL Execution| C{Data Aggregation} C -->|Moving Averages/Outliers| D[Streamlit App State] D -->|Plotly| E[Interactive Visualization] E -->|User Input| D Prerequisites 🛠️ Ensure you have the following stack installed: Python 3.9+ DuckDB : For the heavy lifting. Streamlit : For the UI. Plotly : For the beautiful charts. pip install duckdb streamlit plotly pandas Step 1: Ingesting 100,000+ Data Points in Milliseconds One of the coolest features of DuckDB is its ability to query CSV files directly without a formal "import" step. This is a game-changer for developer productivity. import duckdb import pandas as pd # Let's assume 'heart_rate.cs
产品设计
FTC gives Musk the OK to acquire SpaceX alumni startup Mesh
Mesh came out of stealth in February with a $50 million Series A.
AI 资讯
Why your prototype works for you but not for anyone else
TL;DR — A prototype that works for you but breaks for everyone else usually isn't bad luck. It's four repeatable culprits: you designed for one assembly, your fasteners drift, the enclosure ignores real loads, and you never wrote down why it works. Fix those, and "works on my bench" becomes "works, period." You built the thing, and it works. In your hands, on your bench, every single time. Then a friend tries it, or it sits in the garage a week, or the temperature drops one night, and it just stops. Frustrating doesn't really cover it. Here's the reassuring part: that gap between "works for me" and "works for anyone" is almost always the same small handful of culprits. You're not missing some secret skill. Once you've met them a few times, you start designing around them without even thinking about it. 1. You built it for one. Now build it for two. That first one fit because you were there — nudging, sanding, coaxing it together. The trouble is, all of that lived in your hands, not in the model. So the second copy fights you. If you can't make a second one without the fiddling, it isn't done yet. Bake the clearance into the CAD, then print one you promise not to touch up. That's the real test. 2. Your fasteners are quietly betraying you. Press-fits creep. Hot glue lets go. Jumper wires back out. Double-sided tape taps out the first warm afternoon. I know the boring fixes aren't the fun part — a screw boss, a captive nut, a bit of strain relief, a connector that actually clicks home. But boring is exactly what's still holding a year from now. 3. The enclosure is a load, not a lid. It's easy to treat the box as an afterthought. But heat, dust, and vibration are real forces working on your build. A board that runs cool in the open can slowly cook once it's sealed up. A connector that's happy on the bench can buzz itself loose in a drawer that gets opened every day. Give the heat somewhere to go, mount the board instead of letting it dangle from its wires, and clamp dow
开发者
Anthropic’s Mythos 5 is back
After a rollercoaster negotiation process with the Trump administration that dragged on for two weeks, Anthropic's Mythos 5 is finally back in action - at least, somewhat, for a select group of organizations, according to a letter from the government to Anthropic that was viewed by The Verge. Fable 5, however - the public-facing Mythos-class […]
AI 资讯
Redis Isn't PostgreSQL: Building a Hybrid Change Data Capture Runtime in Ruby
I Built Commercial Redis CDC Source Drivers for Ruby — Here's What I Learned For the past couple of years I've been building a Change Data Capture (CDC) ecosystem for Ruby. Like many CDC projects, it started with PostgreSQL. PostgreSQL's Write-Ahead Log (WAL) is an excellent source of truth: durable, ordered, replayable, and well understood. It provides exactly the properties you want when you're building reliable event pipelines. But the deeper I went into distributed systems, the more I realized something important. Many systems don't observe change from PostgreSQL first. They observe it from Redis. Redis often sits at the front of modern architectures: Redis Streams carry application events. Pub/Sub distributes transient state changes. Keyspace notifications react to cache invalidation and key expiry. Redis Cluster routes events across multiple primaries. In many systems, Redis sees a change before PostgreSQL ever commits it. That raised an interesting question: Can Redis become a first-class Change Data Capture source? The obvious answer is "yes." The interesting answer is "yes—but not in the same way PostgreSQL does." That distinction eventually became cdc-redis-pro , a commercial Redis source driver for the Ruby CDC ecosystem. This article isn't a product announcement. It's an engineering write-up about the architectural decisions behind the project, the tradeoffs Redis forces you to make, and the execution model that ultimately emerged. Redis Doesn't Have One CDC Interface One misconception I frequently encounter is the assumption that Redis has an equivalent of PostgreSQL's WAL. It doesn't. Instead, Redis exposes several completely different mechanisms for observing change. Source Delivery Replay Streams At-least-once Yes Pub/Sub At-most-once No Sharded Pub/Sub At-most-once No Keyspace Notifications At-most-once No At first glance they all look like "events." Operationally they're completely different systems. Streams are durable. Pub/Sub isn't. Keyspace not
AI 资讯
Trump Administration Allows Anthropic to Release Mythos to Select US Organizations
After weeks of negotiations, the White House permitted Anthropic to restore access to its most advanced AI model for a select group of US companies and government agencies.
AI 资讯
Security Profiles Operator hits v1 with stable APIs and a hardening pass
After several years carrying a beta tag, the Kubernetes Security Profiles Operator went 1.0.0 on June 26, freezing eight CRD APIs and clearing a third-party security audit with no criticals. For cluster admins, the practical effect is small but consequential: the syscall and LSM profile a workload runs under is now declared on APIs that will not move under your feet. The release was announced by Sascha Grunert of Red Hat on the CNCF blog. SPO is the Kubernetes operator that manages seccomp, SELinux and AppArmor profiles as cluster-scoped objects, then attaches them to pods. Until now the value proposition was good and the API was provisional. v1.0.0 nails the second half down. What's actually stable All eight CRDs graduated to v1, including SeccompProfile , ProfileRecording , SelinuxProfile , RawSelinuxProfile , and the AppArmor profile type. Conversion webhooks ship with the release, so a cluster running earlier API versions can roll forward without scheduling downtime. The older versions remain available and are slated for removal in a future release. The migration is on the clock, not on fire. The audit pass came with some shape changes that are worth reading before you upgrade. SelinuxProfile swapped its boolean permissive field for a mode enum with Enforcing and Permissive values, which means any GitOps templates that hard-coded permissive: true need a rewrite. RawSelinuxProfile is now gated by an enableRawSelinuxProfiles configuration flag and a validating admission webhook, so the most privileged path through the operator is off by default. AppArmor inputs run through strict regex validation, raw policy payloads are capped at 500 KB, and the eBPF profile recorder picked up explicit resource limits. Why a cluster team should care The point of an operator like this is to take the profile out of the host's filesystem and into the API. That changes the blast radius of "we shipped a container with no profile at all." With SPO and a workload-attached profile, the r
AI 资讯
Why I Built a Tiny Repeated-Game Poker Analysis Tool
Most poker solvers answer one question very well: given a single hand and a single decision tree, what is the equilibrium strategy? (Yes, there is subgame solving, node locking, and plenty more — but the default frame is still one hand, one equilibrium.) I kept getting stuck on a different one. What if the same kind of spot shows up over and over, and a player can commit to a fixed strategy across those repetitions? In a few toy games I had a hunch, worked out by hand, that committing to a fixed strategy could change its value relative to the one-shot picture. I wanted a tool that could make that commitment value precise — to actually analyze it rather than just believe it. (Whether any of this rises to a repeated-game equilibrium is a much stronger claim, and one I am deliberately not making here.) I'm still learning software engineering, so until recently I couldn't implement this — I was stuck reasoning about toy games on paper. AI tooling made the analysis feasible, so I finally started building it: repeated-poker-analysis . It's a small research project: write one narrow model down, run small examples, and record what the model does and doesn't justify. What repeated-poker-analysis is It is an experimental Python toolkit for small abstract poker games. The current MVP covers: fixed Hero commitment candidates, exact Villain best-response diagnostics in small finite trees, candidate generation and filtering, T_deadline , an economic adaptation deadline, local T_detect , an observable-distribution sensitivity estimate, analysis reports and Markdown summaries. It is small on purpose. It is not a full solver and it is not wired to real solver ranges. It starts from one toy game — a river spot — that is tiny enough to inspect and test by hand. That toy spot is one where showdown always chops but rake still bites. In a single-hand view, putting more money into a raked pot can be locally unattractive. Across repeated occurrences the same spot raises a commitment questi
AI 资讯
Tests Pass, Design Breaks: Why TDD Can't Hold the Line on Design Intent
There is a popular misconception that if you do TDD, your design also stays correct. That if the tests pass, quality is guaranteed. In AI-assisted development, this misconception is the kind that quietly accumulates — the more tests you have, the more invisible damage builds up underneath. All tests passed. The design was still broken. Here is what happened today. A function called safe_post.py had its signature changed. Two arguments — notify_sh and doctor_sh — were removed. The test suite passed in full. But the callers were still using the old signature. They were silently broken. Why did the tests pass? Because the test code itself was using the old signature. The tests had been written (by AI) at a time when the design intent was already misunderstood. The misunderstanding was baked into the tests from the start. Tests passing and the design being correct are two different things. "All tests pass" tells you only one thing: the implementation matches what the tests expect. Whether the tests express the right design intent is a separate question. TDD verifies "implementation against tests" — nothing more Let me restate the TDD definition. Red → Green → Refactor. Write a test. Write the implementation that passes the test. Refactor. In this loop, what the test verifies is whether the implementation meets the test's expectation. That is one verification — and only one. What TDD does not verify is whether the test itself correctly expresses the design intent. The structure looks like this: Design intent → Tests (← this link is not verified) ↓ Implementation (← this link is verified by tests) If the person writing the tests misunderstands the design intent, the tests will pass and the design will still be wrong. Machine learning engineer Hamel Husain calls this the "Gulf of Specification" — the gap between what you intended to measure and what your metric actually measures. Optimize hard against a flawed metric and you optimize hard in the wrong direction. The same d
AI 资讯
Post-Mortem Best Practices That Actually Drive Change
The Post-Mortem Nobody Learns From I've sat through hundreds of post-mortems. Most follow the same pattern: something breaks, someone writes a Google Doc, we have a meeting, we list action items, nobody follows up, the same thing happens again in 3 months. Here's how to break the cycle. The Blameless Culture Trap "Blameless" doesn't mean "actionless." The biggest failure mode I see is teams that use blameless culture as an excuse to avoid accountability. Blameless means: we don't punish the person who pushed the bad deploy. Blameless does NOT mean: nobody is responsible for fixing the systemic issue. My Post-Mortem Template # Incident: [SERVICE] [SYMPTOM] on [DATE] ## Impact - Duration: X minutes - Users affected: N - Revenue impact: $X - SLO budget consumed: X% ## Timeline (UTC) - HH:MM - First alert fired - HH:MM - On-call acknowledged - HH:MM - Root cause identified - HH:MM - Fix deployed - HH:MM - Service recovered - HH:MM - All-clear declared ## Root Cause [2-3 sentences. Technical but readable.] ## Contributing Factors 1. [Factor that made the incident possible] 2. [Factor that made detection slow] 3. [Factor that made resolution slow] ## What Went Well - [Something that worked] - [Something that helped] ## What Went Wrong - [Process failure] - [Technical gap] ## Action Items | Action | Owner | Priority | Due Date | Status | |--------|-------|----------|----------|--------| | ... | ... | P1/P2/P3 | ... | Open | ## Lessons Learned [1-2 paragraphs of genuine insight] The Action Item Problem Action items from post-mortems have a 30% completion rate industry-wide. That's terrible. Here's why: Too many items (I've seen post-mortems with 15 action items) No clear ownership No deadline No follow-up mechanism Competing with feature work The Fix: Three Rules Rule 1: Maximum 3 action items per post-mortem. If you can't narrow it to 3, you haven't identified the real problems. Rule 2: Every action item gets a JIRA ticket linked to the next sprint. Not "someday." Not "bac
开发者
BurnAfterRead – E2E encrypted self-destructing drops on Cloudflare Workers
I built a zero-knowledge secret sharing tool. Text and files are encrypted in the browser with AES-GCM 256 before upload - the server only ever sees ciphertext. The decryption key lives exclusively in the URL fragment (#k=...). URL fragments are never sent in HTTP requests (RFC 9110 §4.2.3), so Cloudflare Workers, D1, and R2 never see it - even in logs. A few things I tried to do right: Single-use by default: Durable Objects handle atomic read→decrement→delete with blockConcurrencyWhile, no race conditions on concurrent requests Paranoid mode: returns not_found instead of expired/burned, no timing oracle Revoke endpoint: delete a drop before it's read using a SHA-256'd token with constant-time comparison CLI: burnafter send / burnafter receive - full E2E from terminal, key never touches a browser - /security page with a live in-browser AES-GCM demo and a manual Node.js decryption snippet so you can verify without trusting me Stack: Cloudflare Workers + D1 + R2 + Durable Objects. No third-party crypto libs. Live: https://burnafterread.casablanque.com Source: https://github.com/casablanque-code/burnafterread Verify: https://burnafterread.casablanque.com/security
AI 资讯
What building an LLM inference engine from scratch taught me about compiler design
the insight that started this project hit me while i was finishing a bytecode-compiled language i'd written in C i'd spent months building a hand-written lexer, a single-pass Pratt compiler, a stack VM with 35 opcodes, and a mark-and-sweep garbage collector. and right near the end i had this realization: an LLM inference engine is the same problem. it's a graph-compile plus memory-plan plus kernel-schedule problem. i'd just built one so i decided to find out if that was actually true the project the result is ignis, a from-scratch LLM inference engine in Rust. i used it specifically to see how far the compiler analogy held up. the dependency count ended up at 2: memmap2 (to mmap the weight blob off disk) and fancy-regex (for one look-ahead in the BPE tokenizer). everything else is hand-written, because the whole point was to understand what's actually happening the compiler analogy holds up better than i expected the interesting part of any inference engine isn't loading the weights or doing matrix math. it's what happens between "here's a compute graph" and "here's an efficient execution plan." that's a compiler problem ignis builds an SSA (static single assignment) IR of the entire Qwen2 forward pass. every operation in the transformer (the RMSNorm layers, the SwiGLU activations, the attention projections, all of it) becomes a node in the graph with explicit data dependencies then fusion passes run over the graph. the intuition is simple: if operation B always and only reads the output of operation A, you can merge them into one op and eliminate the intermediate buffer. in practice this fused 49 RMSNorm ops and 24 SwiGLU ops, bringing the total from 435 operations down to 362 that part felt expected. the liveness analysis surprised me the liveness analysis after fusion, the graph still needs activation buffers: scratch memory to hold intermediate results as the plan executes. the naive approach allocates one buffer per node. the smarter approach asks: which buffer