I Stopped Comparing Myself to AI. It Changed Everything.
I have been writing a lot about AI lately, but this one is more personal than usual. Not a tutorial,...
找到 14893 篇相关文章
I have been writing a lot about AI lately, but this one is more personal than usual. Not a tutorial,...
A personal AI agent that runs on your desktop and iPhone Discussion | Link
submitted by /u/ADavison2560 [link] [留言]
submitted by /u/arrrowfox [link] [留言]
AI เขียนโค้ดแทนเราได้แล้ว — แล้วเราจะเหลืออะไรให้ทำ? มีประโยคที่ได้ยินบ่อยขึ้นทุกวัน: "เดี๋ยวนี้ใครยังไม่ใช้ AI ช่วยเขียนโค้ดบ้าง?" คำตอบคือ — แทบไม่มีแล้วครับ ตั้งแต่ GitHub Copilot, Cursor, Claude, ChatGPT ไปจนถึง agent ที่เขียนโค้ดเองได้ทั้ง project — เราใช้ AI ใน level ที่ต่างกัน: Level หน้าตา ตัวอย่าง 🎵 Vibe Coding พิมพ์สิ่งที่อยากได้ กด accept อย่างเดียว "เขียนหน้า login ให้หน่อย" → กด tab tab tab 🧩 Prompt-Guided คิดก่อน ถามทีละส่วน ตรวจทุกอย่าง "สร้าง UserService ที่ใช้ bcrypt hash password" 🛠️ Skill/Lint-Guided ใช้ AI เป็น editor ชั้นสูง — lint, refactor, test "refactor function นี้ให้เป็น table-driven test" 🏗️ Agent-Based ให้ AI run ทั้ง project — spawn subagent, PR, deploy "พอร์ต microservice นี้จาก Express ไป Fastify" แล้วคำถามคือ — ถ้า AI ทำทั้งหมดนี้ได้ แล้วมนุษย์อย่างเราเหลืออะไร? Unit Test — ตัวอย่างที่เห็นชัดที่สุด ลองดู unit test ที่ AI เขียนให้: // 🤖 AI-generated test func TestCalculateDiscount ( t * testing . T ) { tests := [] struct { name string input float64 expected float64 }{ { "zero" , 0 , 0 }, { "normal" , 100 , 90 }, // 10% discount { "max" , 1000 , 800 }, // 20% discount } for _ , tt := range tests { t . Run ( tt . name , func ( t * testing . T ) { result := CalculateDiscount ( tt . input ) if result != tt . expected { t . Errorf ( "got %v, want %v" , result , tt . expected ) } }) } } ดูเผิน ๆ — สวย, table-driven, ถูกต้องตาม Go convention 1 แต่ถามหน่อย — test นี้บอกอะไรเกี่ยวกับ business? "ส่วนลด 10% สำหรับยอด 100 บาท" — ทำไมต้อง 100? เป็นกฎจากที่ไหน? "ส่วนลด 20% เมื่อยอดถึง 1000" — แล้วถ้าลูกค้าเป็น member ได้เพิ่มอีก 5% ล่ะ? input: 0, expected: 0 — test นี้ cover edge case หรือแค่ cover บรรทัด? AI test ได้ถูกต้องตาม function — แต่มัน ไม่รู้ว่า business จริง ๆ คืออะไร AI ไม่รู้ Business Context — และจะไม่มีวันรู้ นึกภาพระบบ e-commerce: ลูกค้าซื้อสินค้า → ระบบตัดสต็อก → คำนวณส่วนลด → คิดค่าส่ง → ออกใบเสร็จ AI แยก test ทีละ function ได้: ✅ TestDeductStock — "ตัดสต็อก 1 ชิ้น" ✅ TestCalculateDiscount — "ส่วนลด 10%" ✅ TestCalculateShipping —
🚀 Build Your First Space Shooter Game with Limn Engine A Complete Step-by-Step Tutorial for JavaScript Beginners Welcome! In this tutorial, you'll build a complete space shooter game using Limn Engine — a zero‑configuration 2D game engine that runs in your browser. What you'll build: A spaceship that moves, shoots bullets, fights waves of enemies, and keeps score. All in about 100 lines of code . By the end, you'll understand: How to create a game loop How to handle keyboard input How to detect collisions How to use particles for visual effects How to manage game state (lives, score, game over) 🎮 Want to play the finished game? Click here to play Space Shooter Live! Before We Start What You Need A text editor (VS Code, Notepad, or any code editor) A web browser (Chrome, Firefox, Edge) Limn Engine — download epic.js from limn-engine-doc.vercel.app What You Should Know Basic JavaScript (variables, functions, arrays, if-statements) How to open an HTML file in a browser No game development experience required! Step 1: The HTML Structure Every Limn Engine game starts with a simple HTML file. <!doctype html> <html> <head> <script src= "asset/epic.js" ></script> </head> <body> <script> // All your game code goes here </script> </body> </html> What's happening: <script src="asset/epic.js"> — loads the Limn Engine library Everything inside the second <script> tag is your game code Save this as game.html and open it in your browser. You should see a blank canvas with a blue gradient background. Step 2: Setting Up the Game The first thing we need is a Display — this is the engine that creates the canvas, runs the game loop, and handles input. const display = new Display (); display . perform (); // Activates performance mode (dual-canvas rendering) display . start ( 800 , 600 ); // Creates an 800×600 canvas What's happening: new Display() — creates the engine display.perform() — turns on high-performance mode display.start(800, 600) — creates a canvas 800 pixels wide and 600 p
Most of us share files constantly: config files, API specs, design assets, build artifacts. And most of us don't think too hard about where they end up. That's exactly what Zero-Knowledge Architecture (ZKA) is designed to address. But the term gets thrown around loosely, so let's break down what it actually means — and what to look for. The Core Idea: The Server Shouldn't Have to Trust You Traditional cloud storage works roughly like this: You upload a file The server encrypts it (or doesn't) The server holds the key You trust them not to look Zero-knowledge flips this entirely. In a true ZKA system: Encryption happens on your device , before data leaves your control The keys never leave your side — the server never sees them The server handles only encrypted blobs — it's a pipe, not a vault The phrase you'll hear is: "We can't read your data even if we wanted to." That's the point. Why This Actually Matters Here's a concrete scenario: you're sharing a .env file with a contractor. You use a cloud service. The service gets breached a week later. With standard encryption (server holds the key): the attacker potentially has your secrets. With ZKA: the attacker has an encrypted blob that's useless without the key they never had. Beyond breach scenarios, ZKA also helps with: Regulatory compliance — GDPR, HIPAA, and similar frameworks become easier to demonstrate when the service provider has zero access to the data Reduced trust surface — you're not trusting the company, their employees, or anyone who might compel them legally What Real ZKA Looks Like in Practice There's a big difference between claiming zero-knowledge and actually implementing it. Here's what to look for: ✅ Client-side encryption Files should be encrypted in the browser or app before upload. Not on the server. If encryption happens server-side, it's not zero-knowledge — it's just encrypted storage. ✅ Key management stays with you Where do the keys come from? How are they shared with recipients? In a rea
Let’s be honest: as developers, our relationship with our office chairs is... complicated. We start the day sitting upright like productivity gurus, but four hours into a debugging session, we’ve morphed into a human pretzel. This "gamer lean" isn't just a meme; it leads to chronic back pain and decreased focus. In this tutorial, we are going to build a real-time posture tracking system using MediaPipe Pose and Computer Vision to save your spine. By leveraging AI productivity tools and the power of cross-platform Electron desktop apps , we will create a silent guardian that watches your form and pings you the moment you start slouching. If you've been looking for a practical way to dive into MediaPipe and Node.js integration, you're in the right place. For those looking for more production-ready patterns and advanced AI implementations, I highly recommend checking out the deep dives at WellAlly Blog . 🏗 The Architecture The system works by capturing frames from your webcam, processing them through a pre-trained neural network to identify body landmarks, and then applying some basic trigonometry to determine if your posture is healthy. graph TD A[Webcam Stream] --> B[MediaPipe Pose Engine] B --> C[Extract 33 Keypoints] C --> D{Geometry Engine} D -->|Angle > Threshold| E[Slouch Detected] D -->|Angle < Threshold| F[Good Posture] E --> G[Electron Main Process] G --> H[System Notification 🔔] F --> I[Wait 5s] I --> A 🛠 Prerequisites To follow along, you'll need: Node.js (v16+) MediaPipe (The pose solution) OpenCV.js (For frame manipulation) Electron (For the desktop shell) 🚀 Step 1: Setting Up the Pose Engine MediaPipe provides a "Pose" model that gives us 33 landmarks in 3D space. For posture correction, we specifically care about the Ears (7, 8) , Shoulders (11, 12) , and Hips (23, 24) . The Math: Calculating the "Slouch" We measure the angle between the Ear, the Shoulder, and a vertical axis. If your ear moves too far forward relative to your shoulder, that's "Forward
A database without relationships is just a spreadsheet with delusions of grandeur. If you've ever stared at a Power BI report showing wrong numbers...totals that don't add up, filters that filter nothing, there's a good chance your data model was broken. Not a bug. Just two tables that should've been talking to each other… and weren't. This is your practical guide to data modeling, schemas, relationships, and joins in Power BI, what they are, how they connect, and how to stop getting burned by them. What Is Data Modeling and How Does It Work? Data modeling is the process of defining how your tables connect to each other inside Power BI's engine (called VertiPaq). Think of it like drawing a map between your tables, telling Power BI this column in Table A is the same thing as this column in Table B. When you load multiple tables into Power BI, it doesn't automatically know they're related. A Sales table and a Products table, sitting separately, can't filter each other. Data modeling builds the bridges. Power BI's model view lets you: Define relationships between tables Set cardinality and cross-filter direction Build star or snowflake schemas Create calculated columns and measures using DAX Under the hood, Power BI compresses and stores each column separately ( columnar storage ). Relationships are resolved in-memory at query time, which is why a well-structured model is blazing fast, and a messy one will bring your report to its knees. Key Concepts | Concept | What It Means | |--------------------------|-----------------------------------------------------| | Fact Table | Stores measurable events (sales, transactions, logs)| | Dimension Table | Stores descriptive context (products, customers) | | Primary Key (PK) | Unique identifier column in a dimension table | | Foreign Key (FK) | Column in a fact table referencing a PK in a dim | | Relationship | The defined link between a PK and FK across tables | | Cardinality | Describes how many rows on each side match | | Cro
One day a multi-site administrator reported a strange bug: "After running the app's SSH connection test 2-3 times, my IP can't reach SSH on that server for a long while ." The errors came back as Connection refused or Connection closed by ... . The server wasn't down, and SSH from a different IP worked fine. The source IP was being temporarily banned at the server. Two external investigation reports gave the cause: server-side protection mechanisms ( fail2ban or PerSourcePenalties in OpenSSH 25+) detect short-windowed authentication failure spikes and temporarily ban the source IP. But the user had only clicked the test button 2-3 times — why were failures "spiking"? The answer turned out to be paramiko's default behavior . paramiko's default — trying many keys per connection paramiko.SSHClient.connect() defaults two options to True : client . connect ( ' host ' , pkey = my_key , # The following are True by default: # look_for_keys=True, # also try ~/.ssh/id_* files # allow_agent=True, # also try ssh-agent registered keys ) When the explicitly passed pkey fails, paramiko falls back through ssh-agent registered keys → ~/.ssh/id_* files → password auth in order. Convenient for developers with a single key. Disastrous for a multi-site administrator: The SSH agent has multiple per-site keys registered ~/.ssh/ holds several id_rsa / id_ed25519 files A single connect call ends up trying 5-10 keys in sequence That blows past the server's MaxAuthTries (default 6) on a single connection So what looked to the user like "one connection test" was being seen by the server as " a suspicious IP racking up 5-10 auth failures in a row ." Repeat that 2-3 times and the protection mechanism declares the IP "exceeded threshold" and bans it. The fix — look_for_keys=False and allow_agent=False paramiko exposes options to scope key trial. We set them explicitly in connect_kwargs : connect_kwargs = { ' pkey ' : my_key , ' look_for_keys ' : False , # don't try ~/.ssh/id_* ' allow_agent ' : F
If you've spent any time building or working with APIs, you've probably realized that the terminal is...
TL;DR A multi-tenant app was resolving the active tenant from the request (subdomain/header) instead of the authenticated user . That makes the client the source of truth for "which tenant am I" — the wrong place for it. Fix: derive the tenant from the user's organization membership, enforce it in middleware, and fail closed. One test locks the behaviour. The bug, in one sentence The request was telling the app which tenant to load, and the app believed it. In a multi-tenant SaaS, every query is implicitly scoped: "give me this tenant's dashboards." If the tenant ID comes from something the client controls — a subdomain, a header, a route param — then the scoping is only as trustworthy as the client. That's a leak waiting to happen. Where the trust should live Think of it like a building pass. The request is someone saying "I'm here for floor 9." The membership record is the pass that says which floors you're actually allowed on. You check the pass, not the claim. Before After Source of truth request (subdomain / header) user's organization membership Who decides the tenant the client the server Failure mode user can land in a tenant they don't belong to resolution fails closed Testable? hard — depends on request shape yes — depends on the user The shape of the fix Resolve the tenant from the authenticated user's organization, in one middleware, before anything tenant-scoped runs: final class SetTenantContext { public function handle ( Request $request , Closure $next ): Response { $org = $request -> user () ?-> currentOrganization (); // No org, no tenant context. Fail closed, never guess. abort_if ( $org === null , 403 , 'No organization context.' ); Tenancy :: setCurrent ( $org -> tenant ); // server-derived, not request-derived return $next ( $request ); } } The key line isn't the setCurrent() — it's that the value comes from $request->user() , not from $request . The user is authenticated; the subdomain is not. request ──> [auth] ──> [SetTenantContext] ──> tena
TL;DR A metrics engine had two query paths — a SQL push-down for big datasets, an in-memory aggregator for small ones. They drifted. The push-down path bound a metric parameter but never added it to the WHERE . With several metric series in one dataset, every query summed across all of them. A KPI that should read 819 read 163,667,603,769 . Fix: put the metric_key predicate in the shared base WHERE so every compile path inherits it, and regression-test both paths assert it. The setup: two paths, one contract A lot of analytics layers compute the same number two ways. For a big dataset you push the aggregation down to the database. For a small one — a preview, a draft dashboard — you pull the rows and aggregate in memory. Faster path, correct path. Both are supposed to return the same value. That's the contract. The dataset stores rows keyed by a metric_key , because one dataset can hold several series at once — say a plain row count and a count-distinct. Each series lives in the same table, told apart only by its key. The bug: a bound param is not a filter The in-memory aggregator filtered by metric_key correctly. The SQL compiler bound a metric parameter into the query... and never referenced it in the WHERE . With a single series in the dataset, it worked by accident — there was nothing else to sum. Add a second series and the math quietly breaks: the query sums across every series. In this case the second series stored hashed values around 1.9 billion each, so the KPI ballooned from 819 to 163 billion. Before After metric value bound, unused bound WHERE predicate (none on metric) metric_key = {metric:String} 1 series in dataset correct (by luck) correct N series in dataset sums across all isolated The lesson is small and easy to miss: binding a parameter only makes the value available — it does nothing until a predicate references it. When one path already returns sane-looking numbers, nobody goes looking. The real fix is parity, not a patch You could bolt the pr
This week's Java roundup for June 22nd, 2026, features news highlighting: the GA releases of Hardwood 1.0 and Endive 1.0; the June 2026 edition of Azul Payara; point releases of Quarkus, LangChain4j; the first beta release of WildFly 41; and introducing Eliya JDK and the Open Source Sustainability Initiative (OSSI), the latter of which was founded by HeroDevs and Commonhaus Foundation. By Michael Redlich
Claude Code & Codex in your Mac notch Discussion | Link
Some of Apple's corporate secrets aren't so secret any more.
Build with your components, colors, fonts, and patterns Discussion | Link
Operation by two Russia-state groups has been ongoing since at least March.
The three-layer model works. Part 1 of this series is the invoice incident that proved it. Part 2 is...
trpc has a scheduled workflow called "Lock Issues & PRs." Its own scorecard shows it failing on almost every run. It is still scheduled, still running, still red. trpc ships excellent software, which is exactly the point: if a project this careful has a workflow that has been red for ages, the rest of us almost certainly do too. It is not a one-off. drizzle-orm has one ("Unpublish release"). cal.com has one ("PR Update"). I scanned 35 popular open-source repos and the same thing kept turning up: a scheduled workflow that fails on nearly every run, quietly, for a long time. Why nobody notices GitHub does email you when a scheduled workflow fails. So how do these survive? Two reasons. First, those emails are routine. You get them for flaky reruns and transient blips too, so you filter them out. Second, a workflow that is always red stops reading as a signal. It is just how that row looks now. I did exactly this on my own project. GitHub emailed me that a workflow had failed. The next day it emailed again. I saw it, told myself I would fix it tomorrow, and promptly forgot. It was my nightly database backup, quietly broken the whole time, and I only caught it when a failure-rate number crept up where I would notice. An always-red workflow is not free It burns minutes every run to produce nothing but a red X. Worse, it trains you to ignore the failure that actually matters: the day a real one lands in the same inbox you have learned to skim past. How to find yours Open your Actions tab and look at the scheduled workflows, the cron-triggered ones nobody watches. If the last several runs are all red, you found one. From the CLI: gh run list --workflow = "Lock Issues & PRs" --status = failure What to do about it Two honest options: fix it, or if the workflow is genuinely abandoned, turn it off. Do not leave it scheduled and red. gh workflow disable "Lock Issues & PRs" Or drop the schedule trigger from the workflow file if it should not run on a timer at all. A disabled work