AI 资讯
Why I left Warehouse out of our Fabric deployment scope
title: Why I left Warehouse out of our Fabric deployment scope published: true tags: microsoftfabric, datawarehouse, cicd, devops Our Fabric deployment pipeline handles sixteen item types. Warehouse is not one of them, and that was deliberate. DEFAULT_ITEM_TYPES = [ " DataPipeline " , " Lakehouse " , " Notebook " , " SemanticModel " , # "Warehouse" is intentionally excluded. Warehouse schema deployment must # be handled separately to avoid schema reset risk during publish. " Environment " , " Eventhouse " , ... ] The reason Publishing a warehouse through this path can reset its schema. Not "might behave unexpectedly". The failure mode is that a deployment intended to be additive removes structure, and the thing that removes it is the same routine that successfully deploys the other sixteen types. The choice that follows Two options once you know that. Include it and hope nobody deploys a warehouse without reading the docs. The pipeline supports everything, and one day someone promotes a change on a Friday and finds out. Or exclude it, document why, and handle warehouse deployment as its own problem with its own tooling. I took the second. An automation that covers most cases and silently corrupts the rest is worse than one that covers most cases and refuses the rest. The refusal is visible. The corruption is not. Making the exclusion loud An exclusion is only useful if someone notices it. Three things help: The comment sits inside the list , not in a doc nobody opens. Anyone reading the item types sees the gap and the reason in the same glance. It is in the README under known limitations, next to the other things the framework does not do. There is a test. It asserts Warehouse is absent from the default scope: def test_warehouse_stays_excluded ( self ): """ Warehouse publish can reset schema, so it is handled separately. """ self . assertNotIn ( " Warehouse " , deploy . DEFAULT_ITEM_TYPES ) That test looks silly. It is asserting that a string is missing from a list.
AI 资讯
Podcast: Will Agentic AI Bring Fantasia’s Sorcerer's Apprentice to Life?: A Conversation with Tracy Bannon
In this podcast, Michael Stiefel spoke to Tracy Bannon about the role of artificial intelligence in software and the attendant risks in the areas of security, software development, and society at large. While it might be reasonable to assume a certain amount of trust within a software ecosystem, the risks escalate when the boundary between two software ecosystems is crossed. By Tracy Bannon
AI 资讯
A WordPress Plugin Changed. Then We Found a PHP Backdoor.
One of the easiest security mistakes is assuming that a WordPress plugin is still trustworthy simply because it has been installed for a long time. The folder is familiar. The plugin name is familiar. WordPress still loads. But is the code on disk still the code you approved? That question became very real for me when MatrixSwarm reported an unexpected change inside a plugin directory on a production server. The alert did not claim that it had discovered malware. It said something more precise and defensible: This plugin no longer matches its trusted baseline. That integrity warning led to a manual investigation. Inside a forgotten WordPress test plugin, I found a PHP backdoor. The important part of this story is not that an automated agent magically understood the attacker’s intent. It did not. The important part is that it noticed a change that was easy for a person—and WordPress itself—to overlook. That incident shaped the design of MatrixSwarm’s WordPress Plugin Guard. The problem: familiarity is not integrity WordPress sites often accumulate history: plugins that are no longer actively maintained; test plugins that were never removed; emergency fixes applied directly on the server; auto-updates that legitimately replace files; abandoned folders that nobody remembers installing; writable PHP files inside a public web root. A traditional malware scanner looks for known suspicious patterns. That is valuable, but it answers a different question. Plugin Guard asks: Has anything inside this approved plugin changed since the operator trusted it? It does not need to recognize a specific web shell. It does not need a signature for a particular backdoor family. It detects the loss of integrity first, then gives the operator evidence and control. How the baseline works When an operator approves a plugin, Plugin Guard walks the plugin directory and computes a SHA-256 digest for every file. It stores those relative paths and hashes as the plugin’s trusted manifest. A simpli
AI 资讯
I verified 51 sets of US tax rules by hand and turned them into a static site
Run the same salary through three different paycheck calculators and you'll get three different answers. None of them explain why. That bothered me enough to spend three weeks building an alternative. The result is payculate.org — a paycheck calculator for all 50 US states and DC where every deduction line opens up and shows its own arithmetic . The interesting problem wasn't the code The tax math itself is straightforward: progressive brackets are a loop, FICA is two multiplications with a cap. I had a working federal calculator in an afternoon. The hard part was that every state is a special case , and a generic model breaks on most of them: Wisconsin has a standard deduction that shrinks as you earn more — it starts at $13,230 and falls by 12 cents per dollar above a threshold, reaching zero around $126,000. Alabama lets you deduct your entire federal income tax before calculating state tax. The more federal tax you pay, the less Alabama income you have. Utah looks flat at 4.5%, but gives a taxpayer credit that phases out with income — so the effective rate climbs while the headline rate never moves. Ohio taxes nothing on the first $26,050, then a flat 2.75%. South Carolina rewrote its entire income tax in March 2026: six brackets became two (1.99% / 5.21%), and the federal standard deduction was replaced by a state-specific deduction that phases out above $40,000 of AGI. That last one I only caught during a routine data check last week. Most calculators I checked are still showing the old six-bracket system. The lines nobody counts The bigger discovery was what national calculators leave out entirely: employee-paid state payroll premiums . Washington charges no income tax at all. But Paid Family & Medical Leave (0.807%) and WA Cares (0.58%, uncapped) still take about $1,040 a year from a $75,000 salary . Most tools show $0 on that line. California's SDI lost its wage cap in 2024 and now takes 1.3% of every dollar — on a $200,000 salary that's $2,600 that appears
AI 资讯
Mastering Idempotent Consumers in MuleSoft for Seamless No-Code Integration Events
Unlock Seamless Idempotent Processing Without Coding Hurdles As a seasoned integration mentor, I'm here to walk you through a simple, no-code/low-code method to tackle the thorny issue of idempotent consumers in MuleSoft Anypoint. You’ve likely struggled with pre-built connectors and complex data transformations, but let’s take this one step at a time—no Java or XML required. The 3-Click Path: From Complexity to Simplicity Define Your Idempotency Key : Start by selecting the unique identifier in your message that will serve as your idempotency key. This could be an order ID, transaction number, or any field that uniquely identifies each event. Set Up Object Store Configuration : Navigate to MuleSoft’s Object Store configuration within Anypoint Studio and configure it for storing these keys. Here, you can choose between In-Memory or Persistent storage options depending on your scalability needs. Apply Idempotent Filter Component : Drag the “Idempotent Filter” component into your flow where you want to enforce idempotency. Configure this filter by specifying the object store and the key field that uniquely identifies each incoming event. And just like that, you’ve set up a system that ensures even when an integration event is delivered multiple times, it will only process once—eliminating double-charges or redundant data entries in your downstream systems. Why This Matters for Low-Level Beginners For many of us working with MuleSoft and similar platforms, the complexity around ensuring message processing integrity can seem daunting. Yet, by simplifying this process through intuitive component usage, we ensure that each event is processed exactly once, maintaining system accuracy without diving into complex scripting or configuration. Conclusion: Empowering Automators As you continue on your journey of automating data flows and enhancing business processes, remember—MuleSoft’s capabilities extend far beyond what rigid pre-built connectors might suggest. Embrace these n
AI 资讯
Nintendo Hotline – What can Product Managers learn?
Nintendo had a hotline where gamers could, at the time, call and speak with 'Game Counsellors' who provided them with tips and walkthroughs. It operated for quite sometime before Nintendo sunset it. There are a few (Product) lessons from this that I am sure will be of value to Product Leaders. 1- Necessity (Invention's mother) : The necessity of a situation usually births the creation of something that stands out from the rest. While Nintendo was not the first to use a phone as a 'business' function, it proved it can be used in the context of a video gaming community. That was their ‘necessity’. "We need a way to accomplish ‘xyz’ " usually turns to creating something specific to that situation. The ‘xyz’ in Nintendo’s case was supporting gamers instantly. It could also be something to support a Product or make it easier for the customer. It could be a feature or it could even be the Product itself. All we need to do is pay attention to our necessities, needs and allow it to guide us. Most people are not paying attention to their needs that’s why innovation and improvements appear difficult. Others know what their necessities are but prioritise wrongly – well that’s story for another day. The point here is simply to build for a necessary problem that exists and not out of assumptions. 2- Know what is available immediately : If necessity is calling, we cannot keep it waiting. We need to look around to know what’s available immediately. In most cases we do not need to go far for solution, we just need to pick what is close by then structure it to align with current needs. Sometimes the necessity demands using/importing an idea from some other place into your own specific area. In retrospect, Nintendo had other options it could have considered at that era in time. During that period, it was common to use print media to relate with the computer (and also gaming) community. There was also postal mail, bulleting boards. I do not know for sure but I am guessing the team at
AI 资讯
What are you working on? #01
What are you working on? I hear these words in my day-to-day. And sometimes, when I hear them, there’s this little brain freeze that happens because my brain is probably trying to put into words the amount of things that have wandered through my head in the last 24 hours. 😂 So I thought, okay, let me try something. I want to take some of those wandering thoughts, explorations, things I'm trying out and things I'm learning, and put them into writing. This is going to be a series where I come and talk about what I'm working on — software engineering, product, work, people, faith, relationships, rest, and whatever else happens to be taking up space in my head at the moment. So, what am I working on? I recently started writing backend code, and there’s a bit of a backstory to that. I built this frontend commerce store years ago where people can come and shop for furniture. At the time, I used a backend-as-a-service to handle the backend side of the application. Now, I’m coming back to that same system and writing the backend myself with NestJS. I wanted to go beyond just consuming a backend and actually understand what is happening behind the scenes. The learning process is a bit stretching at the moment because I’m getting familiar with a lot of new concepts. Tiring and frustrating? Yes. But the feeling when I finally understand the reason behind something is always refreshing. That has been really rewarding lately. I'm also in the middle of launching a mobile application at my workplace, going through system design classes, figuring out how to get the best out of my engineers (AI sub-agents, by the way 😅), and occasionally imagining that dream job where you get to build products that serve millions of people and work with really brilliant minds. Also, I discovered the productivity rush that comes with using large monitors. 😂 Then there's learning how to rest while also trying to close out all the open loops in my head. Building reading habits. Figuring out what to pri
AI 资讯
Unpopular Opinion: Why I’m an AI Skeptic
With all the hype in the past several years around AI (or more specifically GenAI), I'm not afraid to say – I'm an AI skeptic. It doesn't mean that I don't believe that some day AI may have a huge impact on human beings' lives, but at the moment, all I can see is irrational hype. In my background, I came from infra-security; I am not a developer, nor do I consider myself an AI expert. I am a cloud architect, meaning I'm looking at proposed architectures, seeing how they suit business requirements, and whether they are deployed in a secure, resilient, and perhaps cost-effective way. I don't see value in adding AI to every design, just for the sake of saying "our application now includes AI". I've been watching the industry since 2023 go nuts. Suddenly, everyone is eager to add AI capabilities, chasing some unexplained FOMO before the machines replace our jobs. I'm not against the use of AI. As a matter of fact, I've been using Grammarly for many years (since, for most of us, English is not our first language). In the past several years, I've been using chatbots such as ChatGPT, Perplexity, and recently Gemini daily, asking questions about various topics and aspects of my life. From asking the bot to provide me an answer about a specific character in a favorite TV show, to "how do I resolve an alert shown on my car's dashboard," and up to "summarize this blog post for my newsletter". It's great that I can ask Gemini to create me a LinkedIn post based on an article I just read, add some emojis and hashtags, and at the end create me a cover image for the post. For a probabilistic system, this is great. I am expecting the system to be creative and produce me attractive results, sometimes even funny images. For a home consumer, this is great, but far from been ground breaking technology. I truly believe that the "big money" will come from enterprises paying a lot of money for AI-based solutions, once the industry can actually make something good from a non-deterministic s
AI 资讯
DevStacker was supposed to launch, but we found bugs💔
A few days ago I posted here about DevStacker, my app for helping self-taught developers escape tutorial hell and build real projects. We were getting ready to launch it, but then we found some bugs in the login screen. The app itself was working, but the login flow had some issues, and obviously we can't really launch while the first thing users see is broken lol. So we delayed the launch for a bit and we're fixing it now. I'm pretty close to getting everything ready, so hopefully DevStacker will be live very soon. This is also my first app, and honestly I didn't realize how many random things can go wrong until I actually tried to launch one 😭 Anyway, back to fixing login. I'll post again when DevStacker is finally live 🚀
AI 资讯
I Didn't Mean to Build a Programming Language
I'm building a programming language. Written like that, it sounds as if I had always dreamed about compilers, read the Dragon Book cover to cover, and spent years waiting for the day I could finally design my own language. Not even close. I was just writing ordinary web applications and constantly thinking things like: "Why do I have to write it this way here?" or: "Wouldn't this feel better if I could write it a little more directly?" I kept digging into those small annoyances instead of ignoring them, one by one, and somehow they turned into a programming language. It's called Seseragi . Seseragi (せせらぎ) is a Japanese word for the gentle sound or flow of a small stream. I wanted my programming language to have a Japanese name. https://github.com/KentaroMorishita/seseragi https://seseragi.vercel.app/ https://seseragi.vercel.app/tour/ It's still experimental and pre-release, but a Rust compiler, CLI, LSP, formatter, WASM Playground, Signal, and Web UI are already working to a surprising degree. Even I sometimes look at it and think, "How far is this thing going?" It started with being tired of if In 2024, I wrote this article on Qiita. https://qiita.com/KentaroMorishita/items/6329d20fbc6f98f72864 The title alone probably tells you I was already heading somewhere weird. I don't think I hated if itself. What bothered me was the feeling of tracing conditional branches as statements . That was also why I liked ternary expressions. Not just because they were short. They were expressions, so I could take the result directly as a value. const label = isLoading ? " Loading... " : hasError ? " Error " : " Ready " Of course, once these grow, they become painful too. So I started building my own match and when abstractions on top of TypeScript. Looking back, I was trying pretty hard to fight the language. But the underlying desire was already clear: I'd rather construct values than chase control flow. When I look at Seseragi now, the symptoms had started long before the languag
AI 资讯
Reverse-Engineering SWIO: Why Existing CH32V003 Programmers Fail and How I Built One That Works
I wanted to see if an ESP32-S3 could be used as a programmer for the WCH CH32V003 instead of using a dedicated WCH-Link. The final setup is: PC → ESP32-S3 → SWIO → CH32V003 The ESP32-S3 handles the timing-sensitive SWIO communication and the CH32 debug/DMI interface. On top of that I implemented target detection, memory access, flash unlock, page erase, programming, read-back verification and reset/run. Hardware ESP32-S3 N8R2 CH32V003A4M6 (SOP-16) 4.7kΩ–10kΩ SWIO pull-up CP6208 motor driver Small DC motor 3.7V Li-ion battery Breadboard Important connections: ESP32-S3 GPIO10 → CH32V003 SWIO ESP32-S3 3.3V → CH32V003 VDD Common GND External pull-up on SWIO CH32V003 PC4 → CP6208 control input The software stack The programmer is split into several layers: text PC │ │ Python host tool ▼ ESP32-S3 │ │ SWIO ▼ WCH DMI │ ▼ CH32V003 debug module │ ▼ Abstract commands / program buffer │ ▼ Flash controller The ESP32-S3 is doing the SWIO timing directly rather than relying on a separate programmer IC. I used existing open-source CH32/SWIO implementations as references, particularly CNLohr's CH32V003 work and BlueSyncLine's SWIO implementation. Getting SWIO working The first versions did not work. One of the early failures was: SWIO sync: FAILED DMCFGR = 0xFFFFFFFF I had to work through the SWIO startup sequence, timing, receive behavior and physical wiring before getting reliable target responses. Once it was working, the programmer reported: SWIO sync: OK DMI communication: OK Target detect: OK CH32 ID = 0x0713BB91 Target memory read: OK That gave me a stable base for the flash implementation. Flash programming I then added the flash controller operations: flash unlock 64-byte page erase fast page programming read-back verification target reset/run One useful milestone was observing the flash lock transition: FLASH_CTLR before unlock: 0x00008080 FLASH_CTLR after unlock: 0x00000200 After that I tested programming and verification using deterministic data. The programmer was able
AI 资讯
What the browser can actually tell you about your hardware (and what it can't)
I spent a while building browser-based hardware diagnostics and came away with a much clearer sense of where the web platform is genuinely capable and where it quietly lies to you. Notes below, with live demos for each API so you can poke at them yourself. Refresh rate: requestAnimationFrame is the only signal you get There's no screen.refreshRate . The only approach is timing requestAnimationFrame callbacks and inferring the rate from the median frame delta: const deltas = []; let last = performance . now (); function tick ( now ) { deltas . push ( now - last ); last = now ; if ( deltas . length < 180 ) requestAnimationFrame ( tick ); else { const sorted = deltas . slice (). sort (( a , b ) => a - b ); console . log ( Math . round ( 1000 / sorted [ sorted . length >> 1 ])); } } requestAnimationFrame ( tick ); Two gotchas that cost me time. Use the median , not the mean — a single dropped frame wrecks an average. And browsers throttle rAF in background tabs, so the measurement is meaningless unless the tab is visible; gate it on document.visibilityState . ( live version ) Screen dimensions: four different answers, all "correct" screen.width , window.innerWidth , window.devicePixelRatio and screen.availWidth measure genuinely different things, and the one people usually want — actual native panel resolution — is screen.width * devicePixelRatio . Except that's still CSS-pixel derived, so on a scaled display it can disagree with what the panel physically is. The browser simply does not expose true hardware resolution. ( demo ) Keyboard: event.code vs event.key , and the keys you never receive event.key is layout-dependent, event.code is physical position — for a hardware tester you want code . The real limitation is that some keys never reach JS at all: PrintScreen often doesn't fire keydown , Meta combinations get swallowed by the OS, and Fn isn't a browser-visible key on most laptops. N-key rollover testing works surprisingly well though, since you just track the siz
AI 资讯
'We'll fix it later' is a loan. Here's the interest rate
Every time someone on your team says "we'll clean it up later," they're taking out a loan. The problem is that almost nobody checks the interest rate — until it bankrupts an entire sprint. Technical debt is the most-used and least-understood metaphor in software. Used well, the metaphor is genuinely powerful, because debt is exactly the right mental model — including the part everyone forgets: interest. Debt isn't the same as bad code First, a correction. Technical debt isn't just messy or bad code. It's a deliberate or accidental trade: you took a shortcut — skipped the abstraction, hardcoded the value, deferred the test — to move faster now, in exchange for a cost later. Sometimes that's a smart, conscious decision. Shipping today to validate an idea, knowing you'll refactor if it works, is often the right call. The debt isn't the problem; unmanaged, invisible debt is. The interest is the point Here's what the metaphor gets exactly right and most teams ignore. Debt accrues interest . Every feature you build on top of a shortcut is a little harder to build. Every bug in the messy area takes a little longer to fix. The shortcut doesn't cost you once — it taxes every future change that touches it, and that tax compounds. This is why teams mysteriously slow down over time. It rarely feels like a wall; it feels like everything gradually getting harder, estimates creeping up, small changes turning into week-long ordeals. That's compounding interest on debt nobody tracked. I've watched a system's velocity get quietly reclaimed by exactly this, and paying it down deliberately is part of how I approach building things properly . Good debt, bad debt The framework that makes this actionable: Deliberate, prudent debt: "We know the right design, but we're shipping the simple version to hit the deadline, and we'll fix it." Fine — it's a conscious, tracked trade. Accidental, reckless debt: "What's a design pattern?" — debt taken on through inexperience, invisibly, with no plan t
AI 资讯
Clean Code Like a Jedi: The One Principle That Changed My Code Forever
The Quest Begins (The "Why") I still remember the first time I opened a pull request that looked like a novel written by someone who’d had too much coffee. The file was 800 lines long, a single function tried to validate input, fetch data from three different APIs, transform the result, update the UI, and log everything to a console that no one ever looked at. I spent three hours stepping through it with a debugger, only to realize the bug was a typo in a variable name buried three levels deep in a nested if‑statement. When I finally fixed it, I felt like I’d just defeated a dragon… only to discover the dragon had a dozen smaller dragons hiding in its caves. That experience left me wondering: Why does code feel so hard to read, even when it works? The answer wasn’t a fancy framework or a new language feature—it was a simple habit I’d overlooked: making every function do one thing, and do it well . Once I started treating that rule like a sacred oath, the dragons started to shrink, and my code began to feel like a clean, well‑lit hallway instead of a dark, tangled forest. The Revelation (The Insight) The principle is straightforward, yet its impact is massive: each function should have a single responsibility . If you can describe what a function does with a single verb phrase— validateUserInput , fetchUserProfile , renderDashboard —you’re on the right track. If you need an “and” or a “but” in that description, you’ve probably got more than one job packed in. Why does this matter? Readability : A reader can grasp the intent in seconds, not minutes. Testability : Small, focused functions are trivial to unit test. You can mock dependencies and assert outcomes without setting up a whole saga. Debugging : When something goes wrong, the stack trace points you directly to the guilty function, not to a 20‑line monolith where you have to hunt for the offending line. Reusability : A function that does one thing well can be dropped into other parts of the codebase (or even oth
AI 资讯
We Will Get You Through It!
There is a comedy sketch from Bob & Tom that starts with a hilariously impossible promise: overnight delivery by train, from New York to Los Angeles. At one point, someone asks if they can really get a 2,000-pound package across the country overnight by rail. The answer is delivered with absolute confidence: “Norfolk and Waypal, overnight. Absolutely. Positively.” The name is doing some careful work. It lets you hear the phrase that nobody has actually said out loud. No way, pal. When I end up leading a project with six weeks left and something that feels like four months of work to do, I start the internal kickoff by telling the team to go watch that sketch. No other explanation. Just go watch it, then come back. Then I tell them: “Absolutely, positively, we will get you through it. There's Norfolk and Waypal, we are gonna to do it.” That does not mean we are going to do the thing exactly as it was originally promised. It means we are going to get through it. Absolutely. Positively. There is a difference. Laugh at the impossible first I think newer developers especially need permission to laugh at impossible requirements. An 800-pound gorilla from New York to Los Angeles overnight by train is impossible in a way that is easy to laugh at. A project that needs a full cloud environment, API work, a mobile application in the app stores, production deployment, security approvals, and a dozen other things in six weeks? That can feel less funny when it is sitting in your sprint board. But it may be just as impossible if we take the requirements literally. The first danger on a crunch project is shame. A junior developer can look at an impossible deadline and wonder if they are missing something. Maybe everyone else understands how this gets done. Maybe it is a talent problem. Maybe if they just worked harder, they could turn six weeks into twelve. Nope. Sometimes the work is just Norfolk and Waypal . Humor does not solve the problem. It lowers the temperature enough that
AI 资讯
Your `if` statements are a database nobody can query
Somewhere in your codebase there is a line that looks like this: if ( user . plan === ' enterprise ' || user . tenantId === ' acme-corp ' ) { // ... } Nobody remembers who wrote the second half of that condition. It has been there for two years. It is almost certainly still load-bearing. Here is the thing I want to convince you of: that line isn't code. It's data, and it's stored in the worst possible place. Every conditional that encodes a business decision is really a row. It has a condition, an outcome, and a bunch of implicit context about when it applies. You have hundreds of these rows. They're spread across a dozen services, written in four different styles, and there is no way to list them. You have a database. You just can't query it. Five things a database gives you that your code doesn't Once you look at it this way, the problems stop feeling like sloppiness and start feeling structural. There's no schema. One service decides a customer is premium by checking plan === 'premium' . Another checks subscription.tier > 2 . A third checks a flag that was set during a migration in 2023. All three are "the same rule" until the day they aren't, and there's nothing in the system that would notice the drift. There's no way to query it. Try to answer a simple question: what rules are live in production right now? You can't. Someone has to read the source. And grep won't save you, because the interesting conditions are compound, spread across guard clauses, and half of them are expressed as an early return rather than an if . There are no migrations. Changing a rate limit from 100 to 200 requires a pull request, a review, a CI run, and a deploy window. You're pushing a code change through the full pipeline to change a number. It's a schema migration with none of the tooling that makes schema migrations tolerable. There's no audit log. Git tells you who edited the line. It doesn't tell you who decided the rule, when it was supposed to expire, or whether the customer it
AI 资讯
Star Wars: Ahsoka season 2 and Starfighter get teased at D23
Season two of Star Wars: Ahsoka is still months away, but Lucasfilm still took the opportunity to tease it a bit at D23. The company dropped the first trailer for the new season ahead of its January 20th, 2027 debut. The clip shows a darker, witchcraft-filled take on the Star Wars universe, with Grand Admiral […]
AI 资讯
Lean 创始人访谈全记录:当形式化验证遇上 AI,手写数学与软件验证将如何被重塑
https://www.youtube.com/watch?v=KzdYKeAqWhY 题目:《Lean 创始人访谈全记录:当形式化验证遇上 AI,手写数学与软件验证将如何被重塑》 第(一)部分 开场与核心命题:从“测试只能证明有 bug”到“证明可确保无 bug” (0% - 8%) Dijkstra 名言引出形式化验证的根本价值:主持人以 Dijkstra 的名言“程序测试可用于揭示 bug 的存在,但永远无法证明 bug 的不存在”开场,指出 Lean 与形式化证明的意义恰恰在于“证明 bug 不可能发生”。 Lean 的基础定位:Lean 既是一门编程语言(可以写代码),也是一个证明系统(可以对代码写性质并用机器可检查的证明来验证)。它提供绝对正确的保证,并拥有多个独立的检查器。 Lean 应被视为平台:用户可以在 Lean 上写代码、写关于代码的性质命题、并给出证明;本期节目将围绕它如何工作、以及它如何改变数学和软件验证的未来展开,并提出“手写数学是否会终结”这一核心疑问。 第(二)部分 Lean 是什么:编程语言与证明助手的一体两面 (8% - 18%) Lean 的双重身份:Lean 不仅可用于数学证明,也可用于软件验证。基于依赖类型论(Dependent Type Theory)的一族证明助手(如 Rocq/Coq 和 Lean)天然就是“编程语言 + 证明助手”。 软件验证的两种主流路径: • 浅嵌入(Shallow Embedding):通过工具(如把 Rust 翻译到 Lean 的工具)把其他语言映射到 Lean 中进行验证。 • 深嵌入/语义建模:在 Lean 中为 C 语言等编写语义,把 C 程序表示为 Lean 中的数据结构,从而对其陈述性质并进行推理。 具体例子——数组越界验证:以 C 语言访问数组为例,可在 Lean 中把“索引 i 满足 0 ≤ i < 10”写成数学命题;原来的 C 源文件可对应一份“元数据式”的 Lean 证明,由 Lean 逐行检查。 自动化与可维护性:人们会建立自动化框架(如基于前置条件-语句-后置条件的三元组),把证明过程变得更易管理;复杂度是软件验证的大敌,而 AI 的出现让“自动证明”成为可能,但前提是把证明写得模块化以便扩展。 第(三)部分 从“测试套件”到“形式化规格”:为什么规格优于测试 (18% - 28%) 测试 vs. 证明的本质差异:测试套件再全面,也只覆盖了有限场景,角落案例仍可能遗漏;而形式化证明覆盖所有可能情况,真正做到了“bug 的不存在”。 Zlib 压缩库的震撼案例:主持人的同事 Kim Morrison 发起项目,让 AI 把 C 写的 Zlib 压缩库翻译进 Lean,要求通过原测试套件,并证明“压缩后再解压得到原始数据”这一强性质。结果仅用一周就完成了整个形式化,目前只需再做性能优化,且优化不能破坏既有证明。 规格说明(Specification)的成本讨论:写出一份好的规格,工作量因程序而异。一个实用技巧是:先用“低效但正确”的实现作为规格(Spec),再让 AI 生成高效版本并证明其与规格等价。 Jane Street 与工业界实践:Jane Street 等公司已在投资形式化验证,例如对微内核 seL4 的完整验证。过去这类工作在没有 AI 时“手动证明 + 维护证明”的成本极高(往往是写程序本身的 10 倍),而 AI 正在消除这种痛苦——AI 非常擅长撰写和维护形式化证明,即使人已经忘了当初为何这么证。 第(四)部分 Lean 作为编程语言的工程实践与工具链 (28% - 36%) 不仅是证明助手,更是生产级编程语言:AWS 内部有一个约 50 万行 Lean 写的 AI 加速器编译器,主要把 Lean 当编程语言用,顺带获得一些性质证明作为“额外红利”。 工具链体验接近现代语言:构建系统 Lake 相当于 Rust 的 Cargo;编辑器用 VS Code,提供 IntelliSense 等熟悉体验。 Info View——Lean 独有的核心交互界面:屏幕通常一分为二,左侧是代码/证明文件,右侧 Info View 实时显示当前证明目标的状态变化,给用户持续反馈。 Tactic 模式:把证明当成“游戏”:用户通过 by 进入领域特定语言(DSL)来写证明,每一步可简化目标、应用已知引理等,看着目标逐步减少直到归零,过程极具“通关”快感,不少用户戏称自己“沉迷其中”。 第(五)部分 内核信任问题:Lean 自身是否被 Lean 验证? (36% - 42%) 只需信任极小的内核:Lean 整体庞大且规格频繁变动(如简化器的行为不断被用户定制),难以对全部进行形式化;但证明检查的核心——“内核”是可以被规格化的。 多内核策
开发者
The Fix Was Committed. The Old Value Kept Running.
Originally published on hexisteme notes . I deleted three ambient API keys from my shell profile. Then I ran the standard clean-room check — spawn a shell with no inherited environment at all, env -i HOME="$HOME" /bin/zsh -lc 'echo "${VARNAME:-unset}"' , and read unset back for all three. That command doesn't lie: a shell started with an empty environment can only see what the current profile puts there, so if it reports the variable missing, the profile is clean. I closed the loop, reconnected my tools, and moved on. Minutes later I reconnected a review tool I run for cross-vendor sanity checks, and it came back healthy — with eight providers registered, one of them authenticated with a key I had just deleted. Not a cached credential from an old response. A live, working authentication, using a value that no longer existed anywhere on disk. The fix was committed. The old value kept running. Two different questions that sound like one "Did I fix the config?" and "Is the fix in effect?" collapse into a single question in your head, because in the common case they're the same event: you edit a file, the next thing that reads the file gets the new value, done. env -i answers the first question perfectly. It says nothing about the second, because it doesn't test any process that already exists — it only tests a brand-new one, freshly spawned, that has no choice but to read the current profile because it has no environment of its own yet. Every process that was already running before you made the edit is a different story. It read the profile once, at its own startup, copied whatever it found into its own memory, and has not looked at the file since. From that point forward it is not a reader of your shell profile — it is a cache of it. And caches don't invalidate themselves. Finding the actual culprit The process holding the stale value here was the editor I was working in — the same long-lived process that hosts my coding sessions and manages tool connections through M
AI 资讯
Google lowers Gemini 3.7 Flash costs for developers
Google has launched Gemini 3.7 Flash, providing significant updates for coding, automation, and the development of autonomous agents. The company reduced production pricing to help businesses deploy these tools more affordably. This release comes only three weeks after the previous version, signaling a faster pace for developer-focused updates. Accelerated development cycles and cost reduction strategies The introduction of Gemini 3.7 Flash highlights a shift in how technology providers manage their product lineups. Google is prioritizing rapid iteration for its Flash series, which serves as a high-speed tool for developers. This latest version arrived less than a month after its predecessor, showing the company responds quickly to user feedback. Engineers designed this model to handle software engineering tasks and complex, multi-step workflows with higher precision. Pricing for the new model sits at $0.75 per million input tokens and $3.75 per million output tokens. This represents a reduction of approximately fifty percent compared to the prior version. By lowering the financial barrier, Google aims to make large-scale production deployments more sustainable for businesses. The company describes this version as a reliable workhorse capable of following instructions with greater accuracy than previous iterations. While the Flash series moves quickly, the more advanced Pro models follow a different path. These high-end models, designed for the most difficult reasoning tasks, see less frequent updates. During recent financial discussions, leadership at the company did not provide a specific timeline for the next Pro release. This indicates a growing gap between fast, cost-effective models and the slower development of premium intelligence tiers. Industry trends in model tiering Other companies in the industry are following similar patterns by separating their offerings into distinct categories. For example, some competitors have launched high-end variants alongside