Why maintaining a SQL engine in SWI-Prolog became overwhelming for our small team
submitted by /u/Aires_id [link] [留言]
找到 12332 篇相关文章
submitted by /u/Aires_id [link] [留言]
The global memory chip shortage appears to be affecting the availability of Apple’s most popular Mac.
This was first published on the Vibsync blog . Reposting for the DEV community. The short version: AI reliably makes each developer faster. Whether it makes the team faster is a separate question — and the gap between the two is where a lot of quiet cost hides. Below: the five coordination costs that eat the difference, a ten-question diagnostic, and five operating principles. Picture three developers, three AI coding agents, and one repository. Each developer can now produce candidate code, tests, and refactors faster than before. Yet releases move at the same pace, review queues grow, and the same facts keep getting rediscovered. That's not a paradox, and it isn't a reason to slow anyone down. It's a reminder that individual speed and team speed are different quantities , and AI coding agents scale the first far more easily than the second. Give everyone a faster typewriter and you get more pages — not necessarily a better book, written faster, by a group. Individual output is not team throughput It's worth separating two things we tend to blur: Individual output — how much finished work one developer (plus their agent) produces. Team throughput — how much shippable, coherent work the group produces together, after review, rework, waiting, and reconciling everyone's changes. AI agents lift individual output directly. Team throughput is what's left after the coordination overhead is paid, and that overhead doesn't shrink just because each person got faster. A useful way to hold it in your head — not as a formula to compute, just as a shape: team throughput ≈ the sum of local speed-ups − rework − waiting − reconciliation When you add agents, the first term grows. If nothing else changes, the last three grow too — because there's now more work in flight, produced faster, by people who can't all see what the others are doing. The interesting question for a team lead isn't "how do I make everyone faster?" It's "which of those subtraction terms is my real ceiling?" Ther
Most conversations about CRA, DORA, and NIS2 compliance for IoT hardware boil down to one uncomfortable binary: redesign the board around newer, security-capable silicon, or accept that your existing product line falls out of compliance on a fixed deadline. For a product with years left in its lifecycle and a BOM that took months to qualify, "just redesign it" is rarely a real answer. There's a third option that gets far less attention than it deserves: pair the legacy chip with a modern security co-chip that absorbs the cryptographic boundary, while the legacy part keeps doing exactly what it already does well - application logic, peripherals, display, sensor polling. Call it a soft fade-out. The old silicon stays in service until its natural end-of-life; the compliance gap gets closed by a second, much cheaper part sitting next to it, not by replacing it. The Three Gaps a Legacy Chip Has - and Why a Co-Chip Fixes Them The regulatory pressure driving all of this isn't abstract. NIST finalized its post-quantum cryptography standards in 2024, and IR 8547 sets real dates: ECDSA and RSA are deprecated after 2030, disallowed after 2035. Germany's BSI has gone further - TR-02102-1 (2026 edition) sets a stricter 2030 deadline for high-protection-need data, and treats the migration as "alternativlos" (without alternative) rather than a recommendation. Older embedded silicon typically lacks three things simultaneously: a hardware-isolated key store (TEE/APM), side-channel countermeasures (DPA protection) strong enough for physical-access threat models, and enough RAM/compute headroom to run lattice-based PQC algorithms in software without starving the rest of the firmware. Redesigning the whole board to fix all three at once is expensive and slow. But none of those three gaps require touching the part that's already doing its job - they're all boundary problems. A second, purpose-built chip can own the boundary. Three concrete pairings Using the ESP32 family as a worked exa
Also Published On trever.cloud Medium LinkedIn Most of us who get into self-hosting start the same way: start with linux, throw a few apps into Docker, get them running and connectable outside the home network, and call it good for months, maybe even years. Nothing wrong with that approach. A compose file and a spare mini PC gets you further than you think, and if it works and you don't have to think about it, that's a perfectly fine place to stop. Then there's the rest of us. The people who get that first setup running, feel the little spark of "wait, I built this", and immediately start wondering what else is possible. More services. Less babysitting. A real answer to "what happens if this box dies at 2am". If any of that sounds familiar, this one's for you. If you keep going, you'll eventually run into the question every self-hosted setup faces sooner or later, whether you notice it happening or not, "how much should live together, and how much should be kept apart?". Put everything on one box and you quickly feel the fragility when one bad update takes everything down with it. Or when nightly backups put services on hold longer and longer. Split everything into its own isolated piece and you've gained resiliency but now manage a lot of moving parts. Most of the actual learning in running infrastructure happens in the space between those two answers. Where you draw that line is where most of the real infrastructure lessons live. Over the years, I've lived through a few different answers to that question in my own homelab, and each one taught me something the previous one couldn't. It started with a large VM, Docker installed, and every service I wanted to self-host running as a container inside. It was the fastest path to "it's actually working", and at the time that was the whole goal. I didn't know yet what I'd eventually want out of this thing, so keeping the infrastructure simple while I figured that out made sense. That setup carried me a long way, and I don
It happened during a medical appointment. I was sitting in the quiet waiting room, my thoughts occupied by the upcoming consultation, when my phone erupted with a loud, aggressive ringtone. The entire room turned to look at me, and I fumbled to silence it, accidentally hitting the volume up button instead of the mute toggle in my panic. I felt that specific, burning embarrassment that comes from being the person who disrupts a quiet space. I realized then that I had spent years writing code for others, yet I couldn't solve my own basic problem of managing my phone's profile. We live in a world of constant notifications and persistent demands on our attention. The real friction isn't just that phones ring; it's that we are expected to remember to manually toggle settings in a dozen different contexts every single day. Whether it is a classroom, a house of worship, or a professional meeting, the human element of remembering to flip a switch is the point of failure. I wanted an app that handled this silently, without me having to open an interface or even think about the current state of my device. I needed a system that functioned as an extension of my environment rather than an additional task. Building Muffle required me to confront the reality of modern Android background execution. Initially, I thought a simple BroadcastReceiver listening for time changes or geofence triggers would suffice. I was wrong. As soon as the phone entered Doze mode—the power-saving state introduced in Android 6.0—my triggers would either be delayed significantly or killed entirely by the system’s restrictive task scheduler. I had to architect a solution that could survive these aggressive optimizations while remaining battery-efficient. The core of the application resides in a ForegroundService that maintains a persistent notification. While many developers avoid these because of the UI footprint, it is the only way to signal to the OS that your process is performing an essential, user-v
You published a DMARC record months ago. Every checker says it's valid. No reports have ever arrived, and at some point you stopped thinking about it and quietly concluded nobody's forging your domain. You don't know that. You just can't see. Two causes account for almost all of it, and both leave the DMARC record itself looking perfect. 1. Your reporting address never agreed to receive them This is in the spec and almost nobody knows about it. If your rua= address is on a different organisational domain from the domain publishing the record, RFC 7489 section 7.1 requires the destination to explicitly consent. The reason is obvious once you see it: otherwise anyone could point rua= at your mailbox and use the world's mail infrastructure as a free DDoS. Consent is a DNS record, published by the receiving domain: <your-domain>._report._dmarc.<their-domain>. TXT "v=DMARC1" So if example.com sends reports to dmarc@reports.vendor.com , then vendor.com has to publish: example.com._report._dmarc.reports.vendor.com. TXT "v=DMARC1" Without it, conforming reporters send nothing at all. That includes Google, which is most of your report volume. You can watch this working in production. PayPal sends aggregate reports to a third party, and the authorisation record exists: paypal.com._report._dmarc.rua.agari.com. TXT "v=DMARC1;" The practical consequence: not a Gmail address You cannot put a Gmail address in rua= . Google is not going to publish yourdomain.com._report._dmarc.gmail.com on your behalf, and you can't create records in their zone. Same for Outlook, Yahoo, or any address at a domain you don't control. This is a common first move — publish DMARC, point reports at your personal inbox, wait. Nothing arrives, and nothing is wrong with the record. If you use a commercial DMARC service they normally publish these records during onboarding, often via a wildcard. If reports never start after you sign up, check this before anything else. When it doesn't apply: reporting to you
Introduction Managing content efficiently becomes more difficult as Drupal websites grow. Traditional content management structures information in discrete entities but often does not expose meaningful relationships between them. A knowledge graph solves this, connecting content like nodes, taxonomy terms, users and media into an intelligent network. This facilitates semantic search, personalized recommendations and AI-driven applications to enhance how users discover and engage with content. Knowledge Graphs Explained A knowledge graph is a structured representation of linked information. It links related entities by relationships instead of storing content as distinct records. For instance, a Drupal article on cybersecurity might be linked to its author, relevant taxonomy terms, media files, and related articles. These links allow applications to understand not just the content itself, but how it relates to other information across the website. Drupal content mapping Drupal already stores content in a structured way, so it is a good fit for knowledge graphs. Typical entities are: Nodes Taxonomy terms Individuals Media files Custom-entities These entities become nodes in the graph and relationships such as created by, belongs to or references become the edges between them. This provides a richer picture of the content of the website. Selecting a Graph Database Drupal can link to graph databases like Neo4j or Amazon Neptune, where these relationships can be stored and queried efficiently. The typical workflow would be to extract Drupal content, transform it into graph nodes and relationships and synchronize updates through APIs or event-driven processes whenever content is created or modified. Improving Search and Recommendations Knowledge graphs greatly enhance the discovery of content by understanding relationships rather than relying just on keywords. For example, a user looking for Drupal security might also find relevant articles on authentication, access contr
There's a failure mode in SPF that produces no error anywhere you'd think to look. Your record is syntactically valid. dig returns it. Your DNS provider is happy. Your own test mail arrives fine. And yet some of your mail is failing authentication at the receiver, and nothing in your infrastructure will tell you. The cause is usually that you've gone past ten DNS lookups. Ten is a hard ceiling, not a guideline RFC 7208 section 4.6.4 requires evaluators to cap DNS-querying terms at ten. Go past it and the result is PermError — a permanent failure. The important part: receivers don't degrade gracefully. They don't evaluate the first ten and shrug at the rest. They treat the entire record as unusable. You go from "SPF configured" to "SPF absent" in one step, and the only place that's visible is in DMARC aggregate reports, which most people aren't reading yet. Six terms cost a lookup. Four are free. Costs a lookup Free include: ip4: a ip6: mx all ptr exp= exists: redirect= The count isn't yours to control This is what catches people out. The limit applies to the whole resolution tree, not just your record. You publish four includes. One of those vendors publishes six includes of their own. You're at eleven, and your record lists four things. Nothing changed on your side. A vendor updated their record and broke yours. There is no notification for this, from anyone, ever. Counting it by hand You can walk the tree with dig if you want to see it directly: dig +short TXT example.com | grep spf1 Then for every include: you find, recurse: dig +short TXT _spf.vendor.com | grep spf1 Keep going until you bottom out, counting every include: , a , mx , ptr , exists: and redirect= along the way. It's tedious but instructive — you'll usually find one vendor accounting for half your budget. Three traps that make tools lie to you Doing this by hand or with a naive script, there are three places to go wrong. I've seen all three produce confidently incorrect output. 1. redirect= uses = ,
On the latest episode of Equity, we discuss why Sam Altman has calling on the industry to "pace the rate of AI development."
Every portfolio site has the same problem: it's static. A grid of projects, a bio, a contact form — nothing on the page ever changes, which means nothing on the page proves you can work with live data. Recruiters and reviewers skim past it because there's nothing to skim. The fastest fix isn't building your own API — it's embedding someone else's, and picking one that's actually interesting to look at. Here's how to drop a live, auto-updating tech news feed into any site with a single script tag, using NewTqnia , a bilingual (English/Arabic) tech newsroom with a free embeddable widget. Why this is a good portfolio move, not just decoration A static "About Me" page tells someone you can write HTML. A page with a live-updating feed tells them you can integrate a third-party service, handle async content, and think about internationalization (this one supports English and Arabic out of the box) — all real, hireable skills, for the cost of one script tag. Step 1: Build your embed Go to newtqnia.com/en/widget . It's a live configurator, not a docs page — every option you touch updates a preview instantly: Content: custom heading, number of articles, language (English or Arabic), category filter (Artificial Intelligence, Robotics, Space, Health, and others), and ordering (latest first or most popular) Appearance: card / list / compact layout, horizontal or vertical orientation, light / dark / automatic theme, accent color, and toggles for images and summaries Pick settings that match your site — a compact, dark-themed, "Artificial Intelligence"-filtered list looks noticeably more intentional than the default. Step 2: Copy the generated snippet Once you're happy with the preview, the page generates a ready-to-paste embed code block for you — copy it as-is. It'll look roughly like a single <script> tag referencing your chosen configuration, something like: <script src= "https://newtqnia.com/embed/widget.js" data-lang= "en" data-category= "artificial-intelligence" data-count
Your subconscious mind as a living 3D garden you water daily Discussion | Link
Make existing Codex and Claude Code sessions multiplayer Discussion | Link
Markdown & HTML editor, without the LaTeX pain Discussion | Link
Fender CEO Edward "Bud" Cole gave an interview to T3 in May celebrating the 75th anniversary of the Telecaster with comments on AI and music that initially flew under the radar. But it has started making the rounds recently, pouring more fuel on an already raging fire of bad PR following the company pissing off […]
Full title: [Advanced Rust] 2.3. API Design Principles of Unsurprising Pt.3 - Implementing serde Serialize and Deserialize Traits, and Why Copy Is Not Recommended 2.3.1. It Is Recommended to Implement Serialize and Deserialize in serde Serde is the core Rust library for serialization and deserialization : Serialization : converts a Rust struct or enum into a string or binary representation such as JSON or YAML Deserialization : parses a string or binary representation such as JSON or YAML back into a Rust struct or enum Serialize and Deserialize are both traits from the serde crate. Serialize Trait The Serialize trait allows a type to be converted into a serializable data format such as JSON, YAML, or TOML. Its main methods include: serialize_bool serialize_i32 serialize_str serialize_struct These are methods on the Serializer (and related) traits that a Serialize implementation calls; the Serialize trait itself only requires serialize . Its definition is: pub trait Serialize { fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > where S : Serializer ; } Here is an example showing how to implement Serialize manually: use serde :: ser ::{ Serialize , SerializeStruct , Serializer }; struct Point { x : i32 , y : i32 , } impl Serialize for Point { fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > where S : Serializer , { let mut state = serializer .serialize_struct ( "Point" , 2 ) ? ; state .serialize_field ( "x" , & self .x ) ? ; state .serialize_field ( "y" , & self .y ) ? ; state .end () } } serializer.serialize_struct("Point", 2)? creates a struct serializer state, and 2 is the number of fields state.serialize_field("x", &self.x)? serializes the struct fields one by one state.end() finishes serialization Deserialize Trait The Deserialize trait allows Rust types to be parsed from various data formats. Its main methods include: deserialize_bool deserialize_i32 deserialize_string deserialize_struct These are
Full title: [Advanced Rust] 2.2. API Design Principles of Unsurprising Pt.2 - Implementing Clone, Default, PartialEq, PartialOrd, Hash, Eq, and Ord 2.2.1. It Is Recommended to Implement the Clone Trait and the Default Trait Clone Trait The Clone trait in Rust allows an implementer to explicitly create a deep copy of itself through the clone method, as opposed to the by-value copy provided by the Copy trait. Example: #[derive(Debug, Clone)] struct Person { name : String , age : u32 , } impl Person { fn new ( name : String , age : u32 ) -> Self { Self { name , age } } } fn main () { let person1 = Person :: new ( "John" .to_owned (), 25 ); let person2 = person1 .clone (); println! ( "{:?}" , person1 ); println! ( "{:?}" , person2 ); } The Person struct implements the Clone trait In main , person2 clones the data from person1 because it implements Clone Output: Person { name: "John", age: 25 } Person { name: "John", age: 25 } Default Trait The Default trait in Rust allows a type to define a default value and return that default instance through the default() method. Example: #[derive(Default)] struct Point { x : i32 , y : i32 , } fn main () { let p = Point :: default (); println! ( "Point is at ({}, {})" , p .x , p .y ); } Output: Point is at (0, 0) 2.2.2. It Is Recommended to Implement the PartialEq , PartialOrd , Hash , Eq , and Ord Traits PartialEq Trait PartialEq provides support for the == and != operators, allowing custom types to participate in partial equality comparisons. Example: #[derive(Debug, PartialEq)] struct Point { x : i32 , y : i32 , } fn main () { let point1 : Point = Point { x : 1 , y : 2 }; let point2 : Point = Point { x : 1 , y : 2 }; let point3 : Point = Point { x : 3 , y : 4 }; println! ( "point1 == point2: {}" , point1 == point2 ); println! ( "point1 == point3: {}" , point1 == point3 ); } By implementing PartialEq , we can compare whether two structs are equal Output: point1 == point2: true point1 == point3: false PartialOrd , Eq , and Ord Trait
The MCP server for marketing data Discussion | Link
Originally published at wostal.eu . TL;DR : I handed a CI re-platform — GitHub Actions → Argo Workflows, GitHub → Codeberg — to an AI agent. The rewrite looked correct and passed lint, but it didn't account for one thing: the runtime environment had changed completely. The old runner was an external VM; the new one is a pod inside the cluster, where Tailscale IPs aren't routable. Nobody ran the pipeline end-to-end, so every difference stayed as a landmine — six of them. The worst part wasn't the AI's mistake. It was that I spent hours blaming the network when the real culprit was a single missing newline in an SSH key. This is the companion to a different incident. While I was migrating my homelab k3s control plane from SQLite to etcd , the pipeline that ran that migration turned out to be broken in ways that taught me more than the migration itself. In this post I'll cover: Where the mess came from — an AI-assisted CI re-platform that nobody validated end-to-end The phantom CNI bug — hours of chasing MTU, Tailscale, firewall, and conntrack The real culprit — a single missing newline in an SSH key Why early failures hide later ones — six latent bugs, surfaced one at a time The lesson about delegating migrations — to a human or an AI Where the mess came from The entire CI had just been migrated from GitHub Actions to Argo Workflows , and from GitHub to Codeberg — and that migration was handed to an AI agent 🙂. The re-platforming rewrote the logic roughly 1:1, but it didn't catch that the runtime environment had changed fundamentally . The old runner (GitHub Actions / ARC) behaved one way; the new one is a pod in the cluster — from which Tailscale IPs aren't routable, but private IPs are. Nobody (human or AI) ran the pipeline end-to-end, so all of those differences stayed as landmines. That's why there were six latent bugs and the hang I'm about to describe — not random faults, but traces of a GHA→Argo translation that was never validated in the new environment. The p
And will Sony continue to support the PS5 once the PS6 is released?