#LiveReview
freq.org.uk/reviews/wittr-estuary-live/ @stoatie.bsky.social @davepettit.bsky.social Basically, Wolves In The Throne Room are SO back, in what’s been a fantastic year for metal. Long may they continue dethroning the tyrants. #blackmetal #musicreview #livereview
November 12, 2026 at 3:33 PM
Wolves In The Throne Room – Estuary (and live at the O2 Academy Islington) https://freq.org.uk/reviews/wittr-estuary-live/ Basically, Wolves In The Throne Room are SO back, in what’s been a fantastic year for metal. Long may they continue dethroning the tyrants. #blackmetal #msuicreview #livereview
November 12, 2026 at 3:30 PM
freq.org.uk/reviews/oloe-100/ @davepettit.bsky.social Electronic squiggles and bleeps lay the foundation for a rising #drone before .. a traditional, and somewhat unexpectedly jaunty, melody. Nevertheless, the drone remains, at times emerging from the background like an air-raid siren.. #livereview
November 9, 2026 at 2:06 PM
Live Review: Young Miko Is a Bona Fide Superstar, and Her ‘Late Checkout’ Tour at Chase Center Proved It

Young Miko put on a full-scale theatrical production.

punkrockjournalist.com/young-miko-c...

#YoungMiko #LiveReview #LateCheckoutTour #chasecenter #punkrockjournalist
November 10, 2026 at 6:00 PM
Forbidden brought a night of Bay Area thrash metal to Saint Vitus Bar on November 5 with Heathen and Void.

Read Here: metalinsider.net/photos/gig-r...

#Forbidden #SaintVitusBar #Heathen #LiveReview #LivePhotos
Gig Review: Forbidden at Saint Vitus Bar — November 5, 2026
Ian Weber reports on Forbidden, Heathen and Void at the new Saint Vitus Bar in Brooklyn.
metalinsider.net
November 9, 2026 at 11:23 PM
💫 LiveReview автоматизирует проверку PR

LiveReview — система проверки кода с оценкой рисков для бизнес‑критичных систем. До 50% PR могут быть одобрены автоматически.

• Каждому запросу на включение (PR) система присваивает оценку риска
• Безопасные 30–50% PR одобряются автоматически
• Остальные PR…
November 7, 2026 at 5:20 PM
LiveReview
Free, Risk-Aware Code Review: Auto Approve Low-Risk Changes Discussion | Link
dlvr.it
November 7, 2026 at 8:29 AM
LiveReview
Free, Risk-Aware Code Review: Auto Approve Low-Risk Changes Discussion | Link
dlvr.it
November 7, 2026 at 8:28 AM
Is Waylon Wyatt the Next Alan Jackson? Inside the Country Star’s Packed Fillmore Show

A genuine connection with the crowd reveal why this rising country singer is winning hearts.

punkrockjournalist.com/waylon-wyatt...

#WaylonWyatt #theFillmore #livereview #dirtcountry #punkrockjournalist
November 6, 2026 at 10:21 PM
W.A.S.P. and KK's Priest brought a night of classic heavy metal to the Grove of Anaheim on Halloween.

Check out the full recap: metalinsider.net/photos/photo...

#WASP #KKsPriest #BlackieLawless #KKDowning #LiveReview #LivePhotos
Photos/Review: W.A.S.P @ Anaheim w/ KK's Priest -10/31/26
This lineup brought together two important pieces of the soundtrack of the 80s: KK’s Priest and W.A.S.P. brought together two different parts of metal history,
metalinsider.net
November 3, 2026 at 8:38 PM
🎤 LIVE REVIEW 🎤

Apriori at Leo's Red lion Gravesend - 10th October 2026

A night of rock and a peek at what goes on behind the scenes. Read Steve's review on the ERB website.
emergingrockbands.co.uk/live-review-...

#LiveMusic #LiveReview
October 29, 2026 at 11:33 AM
Live Review: Gurriers – Project House, Leeds. 17.10.26

Gurriers tear it up at Project House in Leeds #gurriers #livereview #postpunk #backseatmafia
Live Review: Gurriers – Project House, Leeds. 17.10.26
Gurriers tear it up at Project House in Leeds #gurriers #livereview #postpunk #backseatmafia
www.backseatmafia.com
October 27, 2026 at 4:42 PM
Bleachers and The Linda Lindas Turn Berkeley’s Greek Theatre Into a Masterclass in Modern Rock and Roll

Both bands have developed considerably since their earliest recordings.

punkrockjournalist.com/bleachers-li...

#Bleachers #TheLindaLindas #GreekTheatre #livereview #punkrockjournalist
October 26, 2026 at 8:00 PM
Comentario 'TPcístico' en vivo: THE GATHERING - No nos acreditaron, fuimos igual y nos tomamos 3 pilsen

www.thepichangas.com/livereview/t...
THE GATHERING <BR> No nos acreditaron, fuimos igual y nos tomamos 3 pilsen
Octubre 17/2026, Santander Arena.Debido a la enorme cantidad de medios de prensa -mucho más importantes y masivos que nosotros, claro está- que querían estar presentes en este histórico co
www.thepichangas.com
October 18, 2026 at 11:40 PM
Lean for Developers: Turn Program Requirements into Theorems
_Hello, I'm Shrijith Venkatramana, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. Star us to help devs discover the project, give it a try, and share your feedback to help improve the product._ A test suite can pass while a program still violates an invariant nobody thought to test. A counter exceeds its limit. A retry handler executes a payment twice. A pagination function silently skips records. A resource allocator assigns more capacity than the system has available. These bugs often survive because tests examine particular executions while requirements describe what must hold across many possible executions. What if you could express a requirement as a mathematical proposition, implement the behavior, and ask a computer to verify that your implementation satisfies that proposition? That is the idea behind **Lean** , a programming language and interactive theorem prover. Lean lets developers define functions, express their properties mathematically, and construct machine-checked proofs about those properties. You do not need to formalize an entire application to use it. Start with one function, one invariant, and one proof. ## Tests check examples; specifications define obligations Consider a function that increments a counter without allowing it to exceed a configured limit. An ordinary test suite might cover these cases: * The counter increases when it is below the limit. * The counter stays at the limit when it reaches the limit. * The counter does not exceed the limit when given an unexpectedly large input. These are useful tests. But suppose the function accepts integers in a large domain. How many inputs should you test? Ten? A thousand? A million? For a function over unbounded mathematical integers, exhaustive enumeration is impossible. Property-based testing improves coverage by generating many inputs and checking general properties. Formal verification takes a different approach: it attempts to establish a property for every input in the mathematical domain described by the specification. The distinction is between testing selected executions and proving a proposition about all executions represented by a model. This approach has a long history. In 1969, computer scientist C. A. R. Hoare published _An Axiomatic Basis for Computer Programming_ , helping establish a systematic foundation for reasoning about program correctness. One of the central ideas associated with this work is the Hoare triple: `{P} C {Q}` Here, `P` is a precondition, `C` is a command, and `Q` is a postcondition. Read it as: if `P` holds before executing `C`, then a terminating execution of `C` establishes `Q`. For our counter, we might write: `{current < limit} increment(current) {result = current + 1}` This describes the increment behavior when the counter is below the limit. It does not specify the other cases, such as what happens when the counter has already reached its limit. A complete specification must cover those cases as well. Lean provides a language in which we can represent these requirements precisely and have a proof checker verify the resulting arguments. ## Translate the requirement into a mathematical contract Let's begin with three requirements: * The result must never exceed the limit. * When the current counter is below the limit, increment it by one. * When the current counter is at or above the limit, return the limit. We can express the implementation in Lean: def boundedInc (limit current : Nat) : Nat := if current < limit then current + 1 else limit A few details matter here. `Nat` is Lean's type of natural numbers: `0`, `1`, `2`, and so on. The function receives two natural numbers and returns another natural number. The expression `if current < limit then ... else ...` selects one of two branches, depending on the comparison. Now let's specify the required behavior independently of the implementation. def BoundedIncSpec (limit current result : Nat) : Prop := result <= limit ∧ (current < limit -> result = current + 1) ∧ (limit <= current -> result = limit) This definition introduces three obligations. The expression `result <= limit` says that the result must stay within the limit. The symbol `∧` means logical AND: both propositions must hold. The expression `P -> Q` means that if proposition `P` holds, proposition `Q` must follow. Finally, `Prop` is Lean's type of propositions. The definition `BoundedIncSpec` describes a proposition about the relationship between the inputs and the result. Notice that `result` is an independent parameter. We have described what constitutes a correct result without assuming how the result is calculated. This separation matters. The same specification could be satisfied by different implementations: a conditional expression, a library function, or a more complicated implementation optimized for a particular environment. A specification describes the obligation. An implementation supplies the mechanism. One subtlety deserves attention: our specification is deliberately tailored to natural numbers and the stated requirements. It does not say that the function must preserve information about how far an input exceeded the limit. That is intentional. Formal specification forces us to distinguish essential requirements from incidental implementation details. ## Prove that the implementation satisfies the contract We now have a function and a specification. Can Lean establish that the function satisfies the specification for every possible pair of natural numbers? Here is a complete example for a Lean project using Mathlib, Lean's mathematical library. import Mathlib def boundedInc (limit current : Nat) : Nat := if current < limit then current + 1 else limit def BoundedIncSpec (limit current result : Nat) : Prop := result <= limit ∧ (current < limit -> result = current + 1) ∧ (limit <= current -> result = limit) theorem boundedInc_le_limit (limit current : Nat) : boundedInc limit current <= limit := by unfold boundedInc split_ifs <;> omega theorem boundedInc_eq_succ (limit current : Nat) (h : current < limit) : boundedInc limit current = current + 1 := by simp [boundedInc, h] theorem boundedInc_eq_limit (limit current : Nat) (h : limit <= current) : boundedInc limit current = limit := by have h' : ¬ current < limit := by omega simp [boundedInc, h'] theorem boundedInc_correct (limit current : Nat) : BoundedIncSpec limit current (boundedInc limit current) := by unfold BoundedIncSpec constructor · exact boundedInc_le_limit limit current constructor · intro h exact boundedInc_eq_succ limit current h · intro h exact boundedInc_eq_limit limit current h The main result is the final theorem: theorem boundedInc_correct (limit current : Nat) : BoundedIncSpec limit current (boundedInc limit current) It says that for every natural-number limit and every natural-number counter value, the result of `boundedInc` satisfies the specification. There is no finite test set here. The theorem covers the entire declared input domain. How does the proof work? First, `boundedInc_le_limit` establishes that the result never exceeds the limit. The `unfold` tactic exposes the function definition. `split_ifs` separates the two branches of the conditional, and `omega` solves the resulting natural-number arithmetic obligations. Next, `boundedInc_eq_succ` proves the increment behavior under its precondition. The `simp` tactic simplifies the conditional using the supplied hypothesis. Then, `boundedInc_eq_limit` proves the other branch. Given that the limit is less than or equal to the current value, `omega` establishes that the condition `current < limit` cannot hold. Finally, `boundedInc_correct` combines these three results. The `constructor` tactic decomposes the conjunction into its component obligations. Each obligation is discharged by one of the preceding theorems. The keyword `by` introduces a proof constructed using tactics. Lean checks that the resulting proof establishes the stated proposition. The tactics are convenient ways of constructing proofs; they are not substitutes for proof checking. Lean's trusted kernel checks the resulting proof terms. The distinction is fundamental: the machine is not merely accepting a developer's assertion that the function is correct. It checks a formal argument that the implementation satisfies the proposition. ## Understand exactly what the proof establishes It is tempting to interpret a verified function as a guarantee that the corresponding production feature cannot fail. That conclusion would be too broad. Our theorem proves a property of a mathematical function over natural numbers. It does not prove that a production implementation using a 32-bit integer behaves identically. A 32-bit unsigned integer has a finite representable range. Depending on the language and implementation, arithmetic near the boundary may wrap, trap, or follow other specified behavior. Lean's `Nat` does not impose that machine-level limit. To verify the production version, we would need a model that represents the relevant integer bounds and behavior, then establish the corresponding properties of that model and the implementation. The same distinction applies to external systems. A proof about an authorization function does not automatically prove that a database transaction commits atomically, that a remote identity provider returns trustworthy data, or that a network retry cannot duplicate an external side effect. Those are separate obligations. A useful verification project therefore makes its assumptions and boundaries explicit. What does the function assume about its inputs? Which properties are established by the proof? Which properties depend on the runtime, compiler, database, or external services? These questions are not peripheral details. They determine what assurance the proof actually provides. Lean's architecture helps with this distinction. The language combines programming and theorem proving within a type-theoretic framework, and its kernel checks proof terms produced with the help of tactics. That design allows developers to use automation without treating the automation itself as the ultimate authority on correctness. There is another limitation worth understanding: **a formally verified implementation can satisfy an incorrect specification perfectly.** Suppose the business requirement says a customer must never withdraw more than their available balance. A developer mistakenly specifies that a withdrawal must never exceed the original balance at account creation. Lean might help prove the latter property, but it would not establish that the business requirement had been captured correctly. Formal verification reduces ambiguity in the specification and provides evidence about its implementation. Human judgment remains necessary to determine whether the specification describes the system we actually want. ## Move from function contracts to state invariants Many important software properties concern not just the output of a function, but how a system's state changes over time. Consider inventory management. An application tracks how many units of a product are available and how many have been reserved. When a customer places an order, the system must transfer units from available inventory to reserved inventory. Two requirements are immediate: * A reservation must not consume more units than are available. * A successful reservation must conserve the total number of tracked units. We can represent the state as a structure: structure Inventory where available : Nat reserved : Nat The first field counts available units; the second counts reserved units. Next, define the reservation operation. If sufficient inventory exists, it returns the updated state. Otherwise, it fails. def reserve (i : Inventory) (qty : Nat) : Option Inventory := if qty <= i.available then some { available := i.available - qty reserved := i.reserved + qty } else none `Option Inventory` represents either a successful result (`some updatedInventory`) or failure (`none`). The operation subtracts the requested quantity from the available inventory and adds it to the reserved inventory. It performs no update when the requested quantity is too large. Now we can express a useful invariant: whenever the operation succeeds, the sum of available and reserved inventory remains unchanged. theorem reserve_preserves_total (i : Inventory) (qty : Nat) (next : Inventory) (h : reserve i qty = some next) : next.available + next.reserved = i.available + i.reserved := by unfold reserve at h split_ifs at h with hEnough · injection h with hNext cases hNext simp omega · simp at h The theorem does not merely test a reservation of three units or ten units. It covers every natural-number inventory state and every requested quantity. It says that if the operation returns a successful result, the total tracked inventory is conserved. The key assumption is that the result of `reserve` equals `some next`. In the successful branch, Lean can use that equality to identify the returned state with the state constructed by the implementation. The arithmetic proof then follows from the condition that the requested quantity did not exceed the available inventory. This example demonstrates why it is useful to think in terms of invariants. A state invariant is a property that should remain true across permitted state transitions. Examples include: * The sum of reserved and available resources remains constant. * A financial balance never becomes negative. * A completed order cannot return to the pending state. * A user cannot gain permissions through an unauthorized transition. * A distributed protocol never reaches a forbidden combination of states, under its formal assumptions. In production, inventory correctness involves additional concerns such as database transactions, concurrent reservations, inventory adjustments, and retries. The theorem above proves only a property of the modeled operation. It does not establish that a real database-backed application implements that operation atomically. Even so, the proof provides a precise foundation around which to build the rest of the verification effort. This is a useful pattern for developers: isolate the state transition, write down what must remain true, and prove that each permitted transition preserves the invariant. For a system with many transitions, the proof structure can follow the design of the system itself. ## Integrate specification into the development workflow A proof is most useful when it is part of the regular engineering process rather than an isolated research exercise. One workable process looks like this: :::mermaid flowchart TD A["Write the requirement"] --> B["Define the model and contract"] B --> C["Implement the function"] C --> D["Prove the contract"] D --> E{"Does Lean accept the proof?"} E -->|No| F["Review the code, proof, and specification"] F --> D E -->|Yes| G["Review assumptions and system boundaries"] G --> H["Run tests and verification in CI"] ::: Start with a pure function: a function whose output depends only on its inputs and that has no external side effects. Pure functions are easier to specify because their behavior can be described without modeling a database, network connection, clock, or mutable environment. For an existing application, identify a calculation or state transition and separate it from the surrounding I/O where practical. Define its inputs, outputs, and invariants in Lean. Prove the desired properties and keep those definitions and proofs alongside the implementation. Then add the relevant build and verification commands to continuous integration. If a code change makes a theorem unprovable, the verification build should fail. This is valuable because it turns an invariant into an explicit engineering constraint. Instead of relying on every future developer to remember why a particular condition matters, the team maintains a checked proposition that must continue to hold. Formalization can also improve code review. A reviewer can examine the specification independently of the implementation and ask whether it captures the intended behavior. A second review can focus on the proof and its assumptions. The separation makes two different questions visible: **Are we implementing the right requirement?** **Does the implementation satisfy that requirement?** Those questions are related, but they are not interchangeable. Testing remains part of this workflow. Unit tests exercise concrete examples, integration tests examine interactions with dependencies, and operational monitoring reveals behavior in the deployed environment. Lean contributes another form of evidence: a proof about the modeled properties of the code. A practical adoption strategy is to begin with one small component, integrate its proof into the build, and expand only when the approach proves useful to the team. ## Start with one invariant The most effective first Lean project is probably not a complete application or an attempt to verify every line of an existing codebase. Choose a function with a meaningful invariant: a bounded counter, a pagination helper, a resource allocator, a validation routine, or a state transition. State the requirement precisely, encode the implementation, and prove that the implementation satisfies it. The broader idea has been around since the foundations of program logic. Lean makes this style of reasoning available in a modern programming environment, bringing together executable definitions, mathematical propositions, proof automation, and machine-checked proofs. The shift is from documenting what code is supposed to do to encoding a requirement that a machine can check against a formal model of the implementation. The scope of the guarantee depends on the quality of the specification and the boundary of the model. That makes choosing the right invariant an important engineering task in its own right. **Which invariant in your codebase would be most valuable to turn into a machine-checked theorem?** _ Your team's attention is limited, and the deluge of AI-generated code is making it harder to keep production reliable and secure without slowing you down._ _ I'm building **LiveReview** , a blast-radius aware AI code review built for your business-critical systems. Instead of presenting every diff with equal emphasis, **LiveReview scores each change by blast radius — how far its impact reaches through your call graph — so you can focus attention where it actually matters.** Spend code review effort where business risk is highest — not spread evenly across every diff. ⭐ Star it on GitHub: ## HexmosTech / LiveReview ### Risk-Aware AI Code Review for Business-Critical Systems # LiveReview: Risk-Aware AI Code Review for Business-Critical Systems LiveReview is built for engineering teams that ship often, but also care about keeping production stable for customers. It approves some 40-50% of low-risk changes automatically, and it gives your team the tools to handle the rest: * Understand risky changes faster. * Fix problems in those changes, with human attention directed to the work that needs it. * Enforce your engineering standards. * Learn from production outcomes, such as incidents, rollbacks, and queue wait times. * Improve the review process over time and make it more efficient. * Connect to the major engineering tools that your team already uses. ## Auto-Approve: Ship the Safe 50% Without a Human **Auto-Approve Upto 50% of Your Pull Requests, Safely.** Risk scoring decides which MRs/PRs are safe enough to ship without a human, so your team only spends review time on risky and critical changes. demo.mp4 _LiveReview auto-approving a low-risk change while_ … View on GitHub **Click below to try LiveReview with your codebase:** _ __
dev.to
October 16, 2026 at 8:15 PM
🎤 LIVE REVIEW 🎤

Connor Selby, supported by Mat Day at Login Lounge, Camberley - 1st October 2026

The Login Lounge got down with the Blues and Juliet Hurwitt was there to capture the vibe. Read her full review on the ERB website now.

emergingrockbands.co.uk/live-review-...

#LiveReview #Blues
October 14, 2026 at 4:21 PM
Louder Than Life 2026 brought Iron Maiden, Megadeth, My Chemical Romance, Knocked Loose, Limp Bizkit, Gojira, Tool, Sleep Theory, and more to Louisville.

Check out the recap: metalinsider.net/reviews/revi...

#LouderThanLife #LivePhotos #LiveReview
Louder Than Life 2026: Four Days of Rock and Metal
Four days in Louisville with Iron Maiden, My Chemical Romance, Limp Bizkit, Tool and more. Read our Louder Than Life 2026 review and see the photos.
metalinsider.net
October 13, 2026 at 3:27 PM
AC/DC fired up MetLife Stadium on Friday, October 2, delivering an explosive night in New Jersey.

Check out the coverage: metalinsider.net/photos/gig-r...

#ACDC #MetLifeStadium #ACDCLive #LivePhotos #LiveReview
metalinsider.net
October 6, 2026 at 2:26 PM
Blender for Developers: 15 Concepts Explained Simply
_Hello, I'm Shrijith Venkatramana, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. Star us to help devs discover the project, give it a try, and share your feedback to help improve the product._ You already understand objects, trees, transforms, interpolation, pipelines, coordinate systems, and data structures. Then you open Blender. Suddenly there are meshes, vertices, normals, modifiers, F-curves, armatures, constraints, materials, world space, local space, UVs, nodes, render engines, and approximately 700 buttons. The underlying ideas are much smaller than the interface makes them appear. A useful way to think about Blender is: > **Blender is a system for describing a scene as data, transforming that data over time, and finally projecting it into pixels.** That is much closer to a software system than to a drawing program. This article picks 15 concepts from the Blender vocabulary that give you the most leverage for making small animations. The terminology follows the Blender 5.2 LTS glossary. I will use a simple running example: imagine a cube-shaped owl mascot that jumps into frame, looks at the camera, hops onto a platform, and points at some text. ## 1. Start With the Right Mental Model ### 1. Object An **Object** is Blender's container for something that exists in the scene: a mesh, curve, camera, light, armature, and so on. For a developer, think of it roughly as an entity with: object transform data relationships modifiers animation A cube in Blender isn't fundamentally "a cube." It is an object whose underlying data happens to be a cube-shaped mesh. That distinction becomes important very quickly. Suppose your owl has two identical eyeballs. You can have: Eye_Left ----\ -> same mesh data Eye_Right ----/ The two objects can have different positions and rotations while sharing the same underlying geometry. This is one reason Blender can represent a complicated scene without duplicating everything. ### 2. Data-blocks Blender calls its fundamental named pieces of reusable file data **data-blocks**. Meshes, materials, armatures, node trees and animation actions are examples. The glossary explicitly describes data-blocks as the base units of data in a `.blend` file. This is much easier to understand if you think like a programmer. Imagine: Object A -> Mesh #17 Object B -> Mesh #17 Object C -> Mesh #23 The objects are instances/references to data. This explains many Blender behaviors that otherwise seem strange: * changing an object's transform does not necessarily modify its mesh * two objects can share geometry * materials can be reused * animation data is stored separately * linked data can be reused across files Blender itself grew out of an in-house production tool at Ton Roosendaal's Dutch animation studio NeoGeo. The first Blender source files date to January 2, 1994. The original motivation was partly practical: make a 3D production system where repeated changes from clients were easier to manage. That history explains something about Blender's architecture: it was built around manipulating a production scene, rather than merely drawing individual pictures. ### 3. Transform + Local Space + World Space Every object has a **transform** : location rotation scale Conceptually, you are applying a transformation to geometry. A simplified matrix view is: p_world = M * p_local where: p_local = point in object's coordinate system M = object's transformation matrix p_world = point in world coordinates So if your owl's eye is at: local position = (0.2, 0.0, 0.1) and the owl itself moves across the scene, the eye can move with it without changing its local coordinates. This is exactly the same reason hierarchical transforms exist in graphics engines. A common developer mistake is to ask: > "Why is this object at `(2, 3, 5)` when I set its position to `(0, 0, 0)`?" Often the answer is that `(0,0,0)` is being interpreted in a different coordinate system. Blender distinguishes **world space** from **local space** in roughly the same way a game engine does. One more reason to understand transforms: rotation. Euler rotations are intuitive: rotate X rotate Y rotate Z but the order matters. In certain orientations, two rotation axes can line up and you get **gimbal lock**. Quaternions exist partly because representing and interpolating 3D rotations directly with three sequential Euler angles has these problems. You don't need quaternion mathematics to make your first animation. You do need to know that rotation representation is a mathematical choice rather than merely a UI preference. ## 2. Geometry Is Data, Not a Picture ### 4. Mesh A **mesh** is the classic polygonal representation of a 3D shape: vertices edges faces The glossary defines a mesh exactly this way. Think of it as a graph embedded in 3D. A cube might contain: 8 vertices 12 edges 6 faces The faces are what give the object a surface. This leads naturally to the next concept. ### 5. Topology **Topology** is the arrangement of those vertices, edges and faces. Geometry tells you things such as: "this vertex is here" Topology tells you: "this vertex is connected to these vertices" That distinction becomes extremely important when deforming objects. Suppose your owl is just a hard cube. Topology barely matters. Now suppose you want to turn the cube into a character whose face bends when it speaks. Suddenly topology matters enormously. A rough debugging invariant for a closed genus-0 mesh is Euler's formula: V - E + F = 2 For a cube: V = 8 E = 12 F = 6 8 - 12 + 6 = 2 This doesn't tell you whether a model is aesthetically good. It tells you that the connectivity has certain mathematical properties. A torus, for example, has a different topology: V - E + F = 0 This is one reason graphics programmers sometimes find topology easier to understand than artists do initially: it is literally a graph-structure problem. ### 6. Normals A **normal** is a unit vector perpendicular to a surface. Why should you care about a vector sticking out of a polygon? Because lighting cares. For a simplified diffuse lighting model: brightness ~ max(0, N dot L) where: N = surface normal L = direction toward the light If the surface faces the light: N dot L ≈ 1 If it is perpendicular: N dot L ≈ 0 If it points away: N dot L < 0 and the contribution is clamped to zero. So a huge portion of what your eye interprets as "shape" is actually a consequence of geometry plus normals plus lighting. This also explains why a model can look completely broken after a seemingly harmless edit: sometimes the geometry is fine but the normals are inconsistent. ## 3. Modifiers: Treat Geometry Like a Pipeline ### 7. Modifiers A **modifier** is a non-destructive operation applied on top of existing data. This is one of Blender's most useful ideas. Instead of: mesh -> permanently modify mesh you can have: base mesh | v bevel | v subdivision | v other modifier | v final geometry This is almost exactly how a compiler pipeline or image-processing pipeline feels. You preserve a relatively simple source representation and derive progressively richer representations from it. That has a major operational benefit: > **Keep the source representation cheap to edit.** ### 8. Bevel A **bevel** rounds or chamfers an edge. This sounds trivial. It is one of the highest-return techniques in product animation. Compare: sharp cube with: slightly rounded cube The second catches highlights differently and therefore looks much more like a manufactured object. This matters because the real world almost never contains perfectly sharp macroscopic edges. A two-minute bevel can therefore produce more perceptual improvement than hours of adding geometric detail elsewhere. For your cube owl, you might start with: cube + bevel + material + light and already have something usable. ### 9. Subdivision Surface **Subdivision Surface** takes a relatively low-poly mesh and generates a smoother higher-poly surface. The important intuition is: > You are specifying a coarse control structure and asking an algorithm to construct a smoother surface from it. This goes back to Ed Catmull and Jim Clark's 1978 work on recursively generated B-spline surfaces for arbitrary topological meshes. Their paper is one of the foundations of the subdivision-surface approach used throughout computer graphics. The cost is straightforward. A subdivision step roughly turns: 1 quad -> 4 quads So if you start with 10,000 faces: 10,000 -> 40,000 -> 160,000 -> 640,000 Three levels means roughly 64x as many faces as the starting mesh. This is a recurring graphics lesson: > **A small-looking visual operation can create a huge amount of underlying computation.** For simple product animation, you usually want the lowest-resolution base mesh that gives you enough control, and let modifiers generate detail later. ## 4. The Camera Turns 3D Into 2D ### 10. Shading **Shading** is the process of determining how surfaces appear under lighting. Developers sometimes approach materials backwards: "What color should this object be?" A better question is: "How should this surface interact with light?" Two objects can have the same base color but look completely different because one is: smooth + glossy and another is: rough + diffuse The glossary distinguishes diffuse light, specular light, roughness and related material concepts. This is why lighting is part of modeling. A perfectly modeled object under poor lighting can look worse than a simple object under good lighting. ### 11. Camera Projection A camera decides how the 3D world becomes a 2D image. There are two important projections: perspective orthographic In perspective projection, objects farther away look smaller. A simplified relationship is: x_screen ~ f * x / z y_screen ~ f * y / z So if: z doubles then the projected size is approximately: half This is why a road converges toward the horizon and why a face looks larger when a camera gets close. In orthographic projection, distance does not produce the same scale change. The mapping is conceptually closer to: x_screen ~ s * x y_screen ~ s * y The Blender glossary defines perspective projection by rays converging through an observer point, while orthographic projection uses parallel viewing lines. For a technical product video, orthographic projection can sometimes give the clean "diagram" feeling. Perspective gives the familiar photographic feeling. ### 12. Ray Tracing Ray tracing asks a simple question: > If light travels through this scene, what happens when it hits things? A ray may: hit -> reflect hit -> refract hit -> absorb and continue. That is the conceptual basis of ray-traced rendering. The naive algorithm is expensive. If you have: R rays N triangles then checking every ray against every triangle gives roughly: R * N intersection tests. A scene with: 1,000,000 triangles and billions of rays would obviously be unpleasant. This is why structures such as a **BVH** , or Bounding Volume Hierarchy, exist. Instead of testing a ray against every triangle immediately, the renderer first tests hierarchical bounding volumes and eliminates large portions of the scene. This is a familiar software-engineering pattern: brute force -> spatial index -> avoid work Databases have indexes. Compilers have intermediate representations. Graphics renderers have acceleration structures such as BVHs. ## 5. Animation Is a Function of Time Here is the biggest conceptual jump for a programmer coming into Blender. Animation is not: frame 1 frame 2 frame 3 frame 4 ... It is: property = f(time) Blender's animation system is built around exactly this idea. ### 13. Keyframes A **keyframe** specifies a property at a particular frame. For example: frame 1 -> location.z = 0 frame 20 -> location.z = 3 You do not normally specify frames 2 through 19. You specify the important states. This idea has a direct historical connection to traditional animation. Senior animators created important poses, while other artists filled in the intermediate frames. John Lasseter's 1987 paper, "Principles of Traditional Animation Applied to 3D Computer Animation," described how these traditional animation ideas transfer into 3D computer animation. He discussed principles such as squash and stretch, timing and anticipation using examples including _Luxo Jr._. So when you place two keyframes and let Blender fill in the motion, you are using a very old animation production idea implemented as a mathematical system. ### 14. F-Curves and Interpolation Blender stores the changing value of an animated property in an **F-Curve**. Think: time -> property value For example: frame 0 -> x = 0 frame 25 -> x = 10 The system computes the values between them. The Blender manual describes F-Curves as curves representing animated property values, with time on one axis and the property's value on the other. This is where animation becomes mathematically interesting. A Bézier curve can be written as: B(t) = (1-t)^3 P0 + 3(1-t)^2 t P1 + 3(1-t)t^2 P2 + t^3 P3 0 <= t <= 1 You don't normally calculate this yourself. The important intuition is that: P0, P3 = where the motion starts and ends P1, P2 = influence the shape of the motion That means you are effectively programming velocity and acceleration without explicitly writing a physics simulation. Consider your owl jumping. You might specify: frame 1 -> z = 0 frame 12 -> z = 2 frame 24 -> z = 0 A linear interpolation produces something mechanical. A carefully shaped F-Curve can make the motion: slow -> fast -> slow which your visual system interprets as intentional movement. The mathematics is simple. The difficult part is choosing the function. That is why good animation is closer to control-system design than to drawing. ## 6. Constraints and Relationships: Build the System Once ### 15. Parenting and Constraints **Parenting** creates a relationship in which one object affects another. A child inherits relevant transformations from its parent. Suppose your owl has: Owl | +-- Eye_Left +-- Eye_Right +-- Beak +-- Wing_Left +-- Wing_Right If you move the owl, everything moves with it. You don't need six independent animations. This is another familiar programming pattern: parent transform | +--> child transform Then there are **constraints**. A constraint says, roughly: "derive this object's behavior from some other thing." For example: Camera | +-- look at --> Owl or: Eye | +-- track --> Target The important mental shift is: > **Keyframes describe values. Constraints describe relationships.** That distinction becomes increasingly valuable as a scene grows. Imagine manually animating a camera to follow the owl. You might keyframe: frame 1 frame 10 frame 20 frame 30 ... But if the owl's path changes, the camera animation becomes invalid. A constraint instead captures: camera orientation = function(target position) Now the owl can move differently and the camera can continue following it. This is essentially dependency management. Blender's constraint system even distinguishes between world, local, pose and other spaces, because the mathematical frame in which a relationship is evaluated changes the result. ### What about Armatures and IK? If you move from a cube mascot to an articulated character, you eventually encounter **armatures** , **bones** , and **inverse kinematics**. An armature is a skeleton-like structure made of bones used to control how a character or object moves. With forward kinematics: shoulder -> elbow -> hand you move the parent and the children follow. With inverse kinematics: hand target -> elbow position -> shoulder rotation you specify the result and the system solves backward through the chain. For a simple product animation, you may never need IK. That is an important productivity lesson: > **Learn the concepts your animation actually requires.** A cube owl pointing at a screen can often be built with objects, transforms, keyframes and constraints. You don't need to build a Pixar-style character rig merely because Blender has one. ## 7. The Production Loop: Pixels Have a Price Once you understand the preceding concepts, Blender becomes much easier to reason about as a pipeline: scene data | v geometry | v modifiers | v camera | v shading + lighting | v render | v image Animation adds another dimension: time | +----> transforms | +----> materials | +----> camera | +----> constraints The final result is still just a sequence of images. And that has a very simple operational consequence. Suppose you make a 10-second video at 30 FPS: 10 * 30 = 300 frames At 1920 x 1080: 1920 * 1080 = 2,073,600 pixels/frame Therefore the entire video contains approximately: 2,073,600 * 300 = 622,080,000 pixels So your "10-second animation" is actually around **622 million pixel outputs** before accounting for multiple samples, reflections, transparency, shadows, motion blur, depth of field and other rendering work. That is why render economics matter. A rough mental model is: total render time ~ number of frames * time per frame If a frame takes 20 seconds: 300 * 20 sec = 6,000 sec = 100 minutes Cutting frame time from 20 seconds to 10 seconds saves roughly 50 minutes. But reducing the frame count from 300 to 150 does the same thing. This is why production graphics has a lot in common with systems engineering. You are constantly trading: quality geometry samples resolution memory time against one another. And this leads to a useful rule for small animations: > **Optimize the pipeline, not individual frames.** A badly structured scene that takes 40 seconds per frame is a 200-minute problem. A well-structured scene that takes 5 seconds per frame is a 25-minute problem. ## The 15 Concepts in One Mental Model You can compress almost the entire article into this: 1. Object | 2. Data-block | 3. Transform / coordinate space | 4. Mesh | 5. Topology | 6. Normal | 7. Modifier | 8. Bevel | 9. Subdivision | 10. Shading | 11. Camera projection | 12. Ray tracing | 13. Keyframes | 14. F-Curves / interpolation | 15. Parenting / constraints And then remember the fundamental developer abstraction: scene = data + relationships + functions(time) + renderer Once you see Blender this way, the interface becomes much less mysterious. You aren't learning thousands of buttons. You are learning a fairly small set of abstractions that happen to have a very large UI wrapped around them. Blender itself is a good historical example of why these abstractions matter. It began as a production tool inside NeoGeo, became a commercial product through NaN, and after NaN collapsed in 2002, Ton Roosendaal's "Free Blender" campaign raised enough money to buy back the rights and release the software as GPL open source on October 13, 2002. The interesting part is that much of the software's complexity exists to let you describe increasingly complicated scenes without manually specifying every consequence. That is exactly the kind of abstraction developers should appreciate. ### The practical takeaway For a first useful animation, learn these operations: add object move object rotate object scale object bevel object apply material place camera place light add keyframes edit F-curves parent objects add a constraint render You can make a remarkable amount of professional-looking motion before touching fluids, particles, simulations, sculpting, UV workflows, character rigs or procedural geometry. That is probably the right place to start. **What Blender concept took you the longest to understand, even though it turned out to be conceptually simple?** _ Your team's attention is limited, and the deluge of AI-generated code is making it harder to keep production reliable and secure without slowing you down._ _ I'm building **LiveReview** , a blast-radius aware AI code review built for your business-critical systems. Instead of presenting every diff with equal emphasis, **LiveReview scores each change by blast radius — how far its impact reaches through your call graph — so you can focus attention where it actually matters.** Spend code review effort where business risk is highest — not spread evenly across every diff. ⭐ Star it on GitHub: ## HexmosTech / LiveReview ### Blast-Radius Aware AI Code Review for Business-Critical Systems # LiveReview: Blast-Radius Aware AI Code Review for Business-Critical Systems LiveReview is an AI code reviewer that scores every hunk of a diff by **blast radius** : how far a change reaches through your call graph, how much persistent state it touches, and how well-tested it is. A 3-line change to a shared auth check can outrank a 300-line UI tweak. Your team's attention goes to the highest-risk code first, not spread evenly across every diff. blast-radius-demo.mp4 _LiveReview's Blast Radius & Review Priority scoring, live in the diff viewer._ The exact math, not a black box | Visualize blast radius at a glance | Every factor that feeds the score ---|---|--- | | How does Blast Radius scoring work? (a more technical explanation) **Here's the goal:** * A 3-line fix in a function used by 40 other files, that also writes to a database, should score high. * A 300-line UI change in one file, fully covered by… View on GitHub **Click below to try LiveReview with your codebase:** _ __
dev.to
October 3, 2026 at 8:02 PM
How chDB Turns Ephemeral Agent State into Durable Memory
_Hello, I'm Shrijith Venkatramana, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. Star us to help devs discover the project, give it a try, and share your feedback to help improve the product._ Agent memory sounds like an LLM problem until you actually deploy an agent. A useful agent needs to retain things such as: project conventions previous decisions tool results failed approaches user preferences investigation history Now put that agent inside a temporary CI runner or Lambda or sandbox. Where does all of that state live? A file works well until you need the agent to move to another machine. A remote database solves portability, but introduces a network dependency for every read and write. chDB Durable occupies the space between the two. It keeps the database embedded and local, while using object storage as the durable backing layer. This becomes common as agents move between laptops, CI runners, sandboxes, containers, and short-lived cloud machines. A local agent can accumulate weeks of useful state: project conventions, user preferences, tool failures, corrected assumptions, previous decisions, and the evidence behind those decisions. A SQLite file can preserve some of this. A remote Postgres or ClickHouse server can preserve much more. But there is a useful middle ground: **Keep the database local for fast reads, while making its state durable in object storage.** That is the idea behind the new **chDB Durable Layer**. ## 1. Agent memory is becoming a database problem A useful way to think about an agent is as a loop: observe -> reason -> act -> observe -> reason -> act -> ... Memory sits across this loop. The simplest implementation is often a list of messages: messages = [ "User prefers uv over Poetry", "The checkout service runs in eu-west-1", "Do not modify migrations during deployment", ] Eventually that becomes insufficient. Suppose an agent originally learns: Deploy checkout-api to eu-west-1. Later, someone changes the infrastructure: Deploy checkout-api to eu-central-1. What should the agent store? Just the new answer? Or also: old belief new belief who changed it when it changed why it changed what evidence supported it which agent used the old belief This is where the problem starts looking much more like a database than a prompt. The research literature has been moving in this direction for several years. MemGPT, for example, explicitly treats an LLM agent as a system with multiple memory tiers and a mechanism for moving information between them. The underlying idea is familiar from operating systems: fast working memory is valuable, but larger persistent state must exist somewhere else. Agent memory is therefore partly a **data placement problem**. The interesting question becomes: > Where should the agent's durable state live? ## 2. The SQLite-to-server spectrum has a missing middle There are several obvious answers. ### Local SQLite For a small agent, SQLite is excellent. It is embedded, transactional, mature, and requires no server. An agent can checkpoint its state: agent process | v SQLite file The problem appears when memory becomes historical and analytical. You start wanting queries such as: SELECT project, count() FROM tool_events GROUP BY project; Or: SELECT * FROM memory_history WHERE memory_id = 'deployment-region' ORDER BY version; Or: SELECT model, sum(tokens), sum(cost) FROM events WHERE created_at >= today() - 7 GROUP BY model; That is a different workload from "save my current checkpoint." ### SQLite plus replication You can replicate SQLite's WAL to object storage. That solves the single-disk durability problem. But now there is another component in the deployment: agent | SQLite | replication process | object storage There is more operational machinery, and the underlying database is still fundamentally a transactional row store. ### Remote database The other solution is to put memory into Postgres, pgvector, ClickHouse, or a managed memory platform. This solves portability and shared access. The architecture becomes: agent | network | database server Now every recall is potentially a remote operation. For a conventional application, this is often perfectly reasonable. For an agent, the distinction matters because one user request can generate many sequential tool calls. If an agent makes 10 data-access operations and each introduces 50 ms of network latency: 10 * 50 ms = 500 ms Half a second appears before counting model inference. And that is the optimistic case. Retries, connection failures, authentication, network jitter, and service saturation add another dimension. ### Embedded analytical database Now consider chDB. It puts the ClickHouse query engine inside the application process. agent process | chDB | local database This gives the agent SQL, columnar storage, analytical queries, and local execution without requiring a database server. But one problem remains: **The database is still attached to the machine.** This was the problem the chDB Durable Layer was designed to address. ## 3. The idea: local working copy, durable object The architecture is simple enough to draw on a whiteboard: object storage authoritative state | flush / checkpoint | v +---------------------------------------+ | Agent process | | | | chDB + local MergeTree | | | | recall -> local SQL query | | writes -> local WAL buffer | | | +---------------------------------------+ The crucial distinction is between the **working copy** and the **authoritative copy**. The agent queries its local chDB database. Object storage holds the durable state. When the agent needs to publish changes, it calls: obj.flush() When it wants to create a new base snapshot and shorten future recovery: obj.checkpoint() The result is an interesting deployment shape: No database server No persistent volume requirement No replication sidecar No network call for every recall The durable object has an identity. For example: s3://my-agent-state/agent-memory └── acme-checkout-api The namespace is the storage root. The object is one complete chDB database. That object can later be opened on another machine. This is particularly useful for agents because their compute environment is increasingly disposable. Imagine: Laptop | | develop v CI runner | | test v sandbox | | reproduce bug v another machine The runtime can disappear. The agent's accumulated state does not have to. ## 4. What actually happens during durability? The interesting engineering is underneath the small API. There are four concepts to keep in your head. ### `execute()`: mutate locally An operation such as: obj.execute( "INSERT INTO memories VALUES (...)" ) changes the local working database. The mutation enters the WAL buffer. It has not necessarily become durable yet. ### `flush()`: make a promise real obj.flush() is the durability boundary. When it returns, the writes covered by that flush have reached object storage. That gives application code an important semantic rule: execute() = "I changed my local memory." flush() = "I promise this memory survived the machine." For an agent API, this distinction matters. Consider a tool: remember("The deployment region is eu-central-1") Returning success immediately after `execute()` means the tool may claim to have remembered something that disappears when the sandbox disappears. Returning success only after `flush()` gives the tool an actual durability guarantee. ### `checkpoint()`: create a new base Between checkpoints, the durable state consists conceptually of: base snapshot + WAL segments Recovery therefore looks like: restore base + replay committed WAL = current database As the WAL grows, recovery has more work to do. A checkpoint folds the current state into a new base. So there is a tradeoff: frequent checkpoint -> more transfer work -> shorter recovery infrequent checkpoint -> less transfer work -> more WAL replay This is a familiar database systems tradeoff appearing inside an agent architecture. ### `head.json`: who owns the database? There is another problem. Suppose two workers open: acme-checkout-api at the same time. Both could believe: "I am the writer." That is dangerous. Durable uses a head record with conditional writes to establish lease and fencing semantics. At a high level: read current head = version 17 writer A: CAS(17 -> 18) succeeds writer B: CAS(17 -> 18) fails Only one process becomes the current writer. This gives Durable a deliberate constraint: **one writer per object.** That is a useful property for a per-user or per-project agent brain. It is a poor fit for a team database in which ten independent processes continuously update the same object. ## 5. Store memory as history, not as one giant document This is where using an analytical database becomes interesting. A naive memory system might have: memory.json A more useful design has several relations: memories memory_history raw_transcripts events For example: CREATE TABLE memory_history ( memory_id String, version UInt32, op LowCardinality(String), content String CODEC(ZSTD(3)), edited_by String, edited_at DateTime64(3, 'UTC'), prev_id String, note String ) ENGINE = MergeTree ORDER BY (memory_id, version, edited_at); Now a revision does not destroy the original fact. Instead: version 1: Deploy checkout-api to eu-west-1. version 2: Deploy checkout-api to eu-central-1. You can query the current state. You can also query the history. You can even ask: Why did the agent believe this? Which evidence produced the belief? When did the belief change? How often was this memory recalled? Did those recalls actually help? That last class of questions is important. A memory system should eventually become capable of analyzing its own memory. That is naturally expressed with SQL. ### Raw evidence and actual memory are different One especially useful distinction in the ClickMem design is between **evidence** and **memory**. A transcript may contain: User: "Maybe the service is in eu-west-1?" Tool: "Deployment failed." Agent: "Let's inspect the infrastructure." None of that necessarily deserves promotion into long-term memory. Instead: raw_transcripts = searchable evidence memories = curated beliefs This reduces a common failure mode of memory systems: every conversation -> memory -> future behavior A transient mistake then becomes persistent behavior. The alternative is: conversation -> evidence -> evaluation -> memory That resembles the observation/retrieval/reflection pattern explored in early generative-agent research, but gives the resulting state a conventional data model. ## 6. The math, storage economics, and operational tradeoffs There are two pieces of mathematics worth understanding. ### Semantic recall Suppose every memory has an embedding vector `m`, and the current task has query vector `q`. A common semantic score is cosine similarity: score(q, m) = (q dot m) / (||q|| ||m||) The intuition is simple: same direction -> high similarity different direction -> low similarity A memory query can therefore look like: 1. Filter project 2. Filter active memories 3. Generate semantic candidates 4. Rank candidates 5. Return top K For a brute-force scan with: N memories D embedding dimensions the rough amount of dot-product work is: N * D For example: N = 100,000 memories D = 1,536 N * D = 153,600,000 That is roughly 154 million multiply-add terms for a full scan. Whether that is acceptable depends on hardware, query frequency, and filtering. The useful observation is that memory retrieval is a data-processing problem, so the choice between prefiltering, vector indexes, approximate nearest-neighbor methods, and brute-force scans becomes a database engineering decision. chDB already provides the local analytical machinery around the embedding column; the durability layer does not need to know whether your recall logic is lexical, vector-based, temporal, or some combination. ### Storage is often cheaper than the memory architecture makes it look ClickHouse published an instructive experiment using a 1.45 GB Claude Code transcript sample containing 213,721 rows. Loaded into MergeTree: ZSTD(3): 521 MiB LZ4: 991 MiB So the ZSTD representation is roughly: 521 / 1,383 ~= 0.38 or about a **62% reduction** relative to the original binary size. There was another useful observation: The screenshots represented only about 0.8% of rows, but roughly two-thirds of the bytes. That leads to a practical rule: textual history -> compress in the database large binary objects -> keep outside the table -> store object keys in the database Otherwise your screenshots, audio, or video become part of every checkpoint. ### A rough storage-cost calculation Suppose an agent eventually accumulates: 0.5 GiB compressed durable state Using an illustrative S3 Standard rate of: $0.023 / GB-month the raw storage component is approximately: 0.5 * 0.023 = $0.0115/month about one cent per month. That is not a complete cloud bill. PUT/GET requests, transfer, replication, and the exact storage class and region all matter. But the calculation exposes something useful: **For small per-agent memory stores, storage bytes are unlikely to be the expensive part.** The architectural costs are more likely to come from: inference network calls database operations operational complexity recovery behavior This is why a one-bucket architecture can be attractive. Instead of paying continuously for: database server connection pool database operations persistent volumes replication sidecars you retain a local process and pay for durable state only at explicit boundaries. The tradeoff is that you now own the lifecycle: IAM bucket policies encryption object naming retention flush policy checkpoint policy That is a much smaller operational surface than operating a database cluster, but it is still an engineering responsibility. ## 7. When should developers use Durable? The cleanest decision rule is based on the shape of the workload. Use plain local chDB when: the state is disposable or the state never leaves one machine Use a transactional store when: you mainly need checkpoints and you do little historical analysis Use a server database when: many writers many clients centralized governance large working sets continuous shared access The Durable Layer fits the middle: one logical owner + local analytical queries + append-heavy history + portable durable state A useful deployment might look like: S3 / GCS / Azure | durable agent object | +--------------+--------------+ | | laptop CI runner | | chDB chDB | | local SQL local SQL | | recall recall The database moves. The query engine stays embedded. The service layer disappears. And the boundary between "memory" and "data engineering" becomes much thinner. There is also a nice historical symmetry here. ClickHouse itself began at Yandex under Alexey Milovidov and colleagues as an attempt to generate real-time analytical reports from continuously arriving, non-aggregated data. Its early production system eventually became the engine behind Yandex.Metrica. Years later, the same broad philosophy is useful for agents: keep the raw history store it efficiently query it later derive answers from the history The difference is that the data is now an agent's experiences rather than web analytics. That may be one of the more useful ways to think about agent memory. **Memory is a database that happens to influence future decisions.** And once you view it that way, persistence, provenance, revision history, compression, query latency, leases, checkpoints, and recovery stop looking like infrastructure details. They become part of the agent's cognitive architecture. The chDB Durable Layer is interesting because it gives developers a missing deployment primitive: embedded analytical state + portable durability + object storage + no database server The result is a local agent brain that can survive the machine that created it. What do you think the right primitive for long-lived agent memory should be: a vector store, a transactional database, or an analytical database with durable local state? _ Your team's attention is limited, and the deluge of AI-generated code is making it harder to keep production reliable and secure without slowing you down._ _ I'm building **LiveReview** , a blast-radius aware AI code review built for your business-critical systems. Instead of presenting every diff with equal emphasis, **LiveReview scores each change by blast radius — how far its impact reaches through your call graph — so you can focus attention where it actually matters.** Spend code review effort where business risk is highest — not spread evenly across every diff. ⭐ Star it on GitHub: ## HexmosTech / LiveReview ### Blast-Radius Aware AI Code Review for Business-Critical Systems # LiveReview: Blast-Radius Aware AI Code Review for Business-Critical Systems LiveReview is an AI code reviewer that scores every hunk of a diff by **blast radius** : how far a change reaches through your call graph, how much persistent state it touches, and how well-tested it is. A 3-line change to a shared auth check can outrank a 300-line UI tweak. Your team's attention goes to the highest-risk code first, not spread evenly across every diff. blast-radius-demo.mp4 _LiveReview's Blast Radius & Review Priority scoring, live in the diff viewer._ The exact math, not a black box | Visualize blast radius at a glance | Every factor that feeds the score ---|---|--- | | How does Blast Radius scoring work? (a more technical explanation) **Here's the goal:** * A 3-line fix in a function used by 40 other files, that also writes to a database, should score high. * A 300-line UI change in one file, fully covered by… View on GitHub **Click below to try LiveReview with your codebase:** _ __
dev.to
September 30, 2026 at 7:57 PM