home.social

Search

285 results for “arri”

  1. Molt bon dia veïnes i companyes!

    La vaga per un habitatge i un treball digne ja és una realitat!

    El sindicalisme d’habitatge i laboral hem fet una aposta clara per acabar amb el negoci de l’habitatge i la classe política que el permet.

    La vaga només pot triomfar si la treballem entre totes, si la fem arribar a cada col·lectiu, a cada barri i cada centre de treball.

    És per això que hem creat el Comitè de Vaga del districte de St. Andreu. Un espai d’unió entre moviments socials i individualitats que ens permetrà organitzar-nos per fer arribar aquesta vaga a tot arreu.

    Us convidem a totes a participar a la segona assemblea oberta del comitè el dimarts 27 d’octubre a les 18h als Jardins d'Isabel Domínguez Paniagua, davant del Lidl del Bon Pastor.

    Vine, participa.
    Organitzem la resposta popular!

    #SantAndreudelPalomar #manifestació #assemblea #sindicathabitatge #vaga #vagageneral #VagaXHabitatge #vagageneral11n #vaga11n

  2. The architects of this campaign remain unknown, which honestly only adds to the elegance.

    Apple iPhones are the intended destination, and the sites themselves don't even know they're part of the blueprint. Genuinely admirable structural malevolence.

    Website operators should monitor traffic for anomalous outbound behavior and audit security configurations before the next tour group arrives. (2/3)

  3. ACH Return Codes Explained: R01, R03, R10 & How to Handle Them

    ACH Return Codes Explained: R01, R03, R10 & How to Handle Them


    When you're building a payout system, ACH returns are inevitable. A transaction settles, but then days later—sometimes up to five business days—a return code arrives telling you the money is coming back. Understanding what each code means is the difference between a resilient payment flow and a broken one.

    This guide covers the most common ACH return codes you'll encounter, what triggers them, and how to handle them in your integration.

    What Is an ACH Return Code?


    The National Automated Clearing House Association (Nacha) defines a standardized set of return codes (R01 through R85) that banks use to reject ACH entries. Each code maps to a specific reason: insufficient funds, closed account, unauthorized debit, routing errors, and more.

    When a return arrives, your processor sends it back to you via webhook or API response. The return includes:

    • The original transaction ID
    • The return code (e.g., R01)
    • The reason text
    • The amount being reversed
    • The return date

    Your job: parse it, log it, notify the user, and decide the next action.

    The Big Three: R01, R03, R10

    R01: Insufficient Funds


    What it means: The recipient's account doesn't have enough balance to cover the debit.

    When it fires: Usually within 1–2 business days, during the bank's posting cycle.

    Why it matters: This is temporary. The user might deposit funds tomorrow. It's a retry candidate.

    How to handle it:

    {
    "return_code": "R01",
    "original_amount": 50000,
    "cents": true,
    "action": "retry_later",
    "retry_window_days": 3
    }

    Schedule a retry in 2–3 days. Update your UI to show the user: "Payment pending — will retry on [date]." If it fails twice, escalate to manual review or suggest an alternate payment method.

    R03: No Account / Unable to Locate Account


    What it means: The routing number and account number combination doesn't exist, or the account has been closed.

    When it fires: Usually 1–3 business days.

    Why it matters: This is permanent. The account is gone. Retrying won't help.

    How to handle it:

    {
    "return_code": "R03",
    "action": "fail_permanently",
    "notify_user": true,
    "message": "The bank account you provided is inactive or invalid. Please verify and re-enter."
    }

    Flag the bank account as invalid in your database. Require the user to re-enter or re-verify. Don't retry.

    R10: Unauthorized Debit


    What it means: The recipient (or their bank) claims they never authorized this ACH debit. Common in B2C payouts where the user disputes the charge.

    When it fires: 3–5 business days (often as a chargeback-style dispute).

    Why it matters: This is a fraud or authorization signal. The recipient is actively contesting the payout.

    How to handle it:

    {
    "return_code": "R10",
    "action": "investigate",
    "escalate_to": "compliance",
    "preserve_evidence": true,
    "message": "Recipient disputes this payment. Review authorization records."
    }

    Don't retry. Escalate to your compliance team. Check your records for proof of authorization (e.g., signed agreement, API consent token, timestamp). If authorization is weak, you may need to refund from your own account.

    Building Retry Logic


    Here's a simple state machine for handling returns:

    Return CodeCategoryActionRetry?Max AttemptsR01, R02, R09TemporaryRetryYes3R03, R04, R05Account IssueFailNo—R10, R29AuthorizationEscalateNo—R20, R21, R22Format ErrorFailNo—R31, R32Routing ErrorInvestigateMaybe1

    Implementation Pattern


    javascript
    async function handleAchReturn(returnEvent) {
    const { returnCode, transactionId, amount } = returnEvent;

    if (['R01', 'R02', 'R09'].includes(returnCode)) {
    // Retry logic
    await scheduleRetry(transactionId, amount, 2); // retry in 2 days
    await notifyUser(transactionId, 'pending');
    } else if (['R03', 'R04', 'R05'].includes(returnCode)) {
    // Permanent failure
    await markAccountInvalid(transactionId);
    await notifyUser(transactionId

    ---

    *Decoding ACH return codes programmatically? The [ACH Return Codes API](rapidapi.com/payoutrail-ach-re…) returns the full Nacha R01–R85 set with plain-language descriptions and handling guidance.*#backend #fintech #softwaredevelopment #software #coding #development #engineering #inclusive #community
    ACH Return Codes Explained: R01, R03, R10 & How to Handle Them

  4. From a terrific piece by Stephanie Campbell on what good energy policy does/not look like, with a focus on the Australian case:

    ‘Bell Bay, which already runs almost entirely on renewable electricity, was excluded from the government’s Green Aluminium Production Credit because the program rewards additional emissions reductions. But producing aluminum with cleaner energy is one goal; keeping the smelter competitive enough to stay open is another. If electricity costs make production uneconomic, Australia could lose an important industry despite its abundant energy resources.

    ‘But it does not address whether that [energy] transition will leave enough industrial capability and resilience or whether replacement capacity will arrive on time.

    ‘[Australia] should compare all available technologies on cost, reliability and practical value. If nuclear cannot compete, the market can show that. Banning it in advance prevents that comparison.

    ‘Australia did not run out of energy. It ran down its options’.

    japantimes.co.jp/commentary/20 

  5. Meta's personal AI agent, Muse, launched in Japan on October 23, 2026 — its first market outside North America.

    That one sentence matters more than it looks. A month ago, the proactive-agent race was an American story. Now it has a second country, a second language market, and a clear signal about where this contest is actually fought: not just on model quality, but on distribution geography and connectors.

    What launched in Japan


    Muse debuted in the US and Canada in September. Japan is the first expansion beyond North America, and it arrives on all three surfaces that matter: iOS, Android, and the web. Basic functions are free, with subscriptions unlocking more.

    That is the shape of the whole category right now. Free to try, paid to go further, and rolling out country by country rather than everywhere at once. If you are building anything that plugs into these agents, the rollout map is your roadmap — your users in Tokyo just joined your users in Toronto.

    The field, in one sweep


    Muse did not land in an empty market. Within the last few weeks, every major lab has put its own proactive agent on the board:

    Anthropic's Claude Duet opened as a research preview on October 21, 2026. It is waitlisted, limited to US Pro and Max subscribers for now, built on Claude Opus 5.5, and it leans hard on connections: more than 6,000 connectors, a morning brief, and — the detail developers should steal — it asks before it sends, pays, or deletes anything.

    OpenAI's Dots launched in late September for ChatGPT Pro and Business Premium users, bringing proactive, multi-step work to the largest existing chatbot audience.

    xAI's Grok Bot has been out since August 11, built around multi-agent teams rather than a single assistant doing everything.

    Four labs, four agents, four different bets. And one shared pattern: none of them is simply open to everyone yet.

    Why this is about geography and connectors now


    Here is the honest read, based on the announcements and coverage rather than hands-on testing: the models are no longer the differentiator. Every lab has a strong model. What differs is who can reach users, where, and what the agent can actually touch once it gets there.

    Japan is Meta's answer to the reach question. Duet's 6,000-plus connectors are Anthropic's answer to the touch question. Dots' bet is that the ChatGPT audience itself is the distribution. Grok Bot's bet is that teams of agents beat one generalist.

    For developers, that reframes the work. The winning integration is probably not "support the smartest agent." It is "support the agent your users already have, in the country they live in, with the tools they already use" — and design your permission model like Duet does, where the agent checks before it does anything irreversible.

    That last point deserves emphasis, because it is where this whole category will win or lose trust. An agent that sends, pays, or deletes without asking is a liability with a nice voice. An agent that asks first is a colleague. Duet's rule — ask before send, pay, or delete — should be the default every developer demands from every agent they build on, regardless of which lab wins.

    The honest catch


    Every one of these agents is still gated. Muse is in three countries. Duet is waitlisted and limited to US Pro and Max subscribers. Dots sits behind Pro and Business Premium plans. Grok Bot aside, "proactive AI for everyone" is a headline, not a reality — yet.

    So do not rebuild your product around any single agent this week. Build the connector layer once, keep the permission checkpoints yours rather than the agent's, and watch the rollout maps. The lab that reaches your users' country with the connectors your product needs will pick your winner for you.

    What to watch next


    Three things, in order. First, which country Muse enters next — the pace of that map tells you how fast Meta thinks it can scale this. Second, whether Duet's waitlist opens wider, and whether its connector count becomes the number every rival has to match. Third, whether any lab drops the gating entirely and goes for raw reach. The first one to do that changes the race overnight.

    The agent war went global this week. It just has not gone universal yet — and that gap is where developers still have time to get ready.

    Based on the announcements and coverage: MacRumors (October 21, 2026) on Claude Duet, GenZ NewZ (October 24, 2026) on Muse in Japan, and AI Stack Crunch (October 23, 2026) on the wider agent roundup. No hands-on testing is claimed in this article.

    FAQ


    When did Meta's Muse launch in Japan?
    October 23, 2026 — its first market outside North America after the September debut in the US and Canada.

    What platforms is Muse available on?
    iOS, Android, and the web, with basic functions free and subscriptions for more.

    What is Anthropic's Claude Duet?
    A research preview opened October 21, 2026, waitlisted and limited to US Pro and Max subscribers, built on Claude Opus 5.5, with 6,000-plus connectors, a morning brief, and a rule of asking before it sends, pays, or deletes.

    What are OpenAI's Dots and xAI's Grok Bot?
    Dots launched in late September for ChatGPT Pro and Business Premium users. Grok Bot launched August 11, built around multi-agent teams.

    Why does the Japan launch matter for developers?
    Because the contest is now about distribution geography and connectors, not just model quality — and every agent in the race is still gated by region, waitlist, or plan.#ai #agents #meta #automation #software #coding #development #engineering #inclusive #community
    Meta's Muse Just Landed in Japan — and the Proactive Agent War Just Went Global

  6. Good morning Fedi friends. Sunday morning, the day most people sleep in - me at 5am - wide awake &🫪. Mind you it wasn’t a bad sleep a little restless because it was warm & having shoulder issues, but that’s not unusual.
    I stood on the back lawn pre dawn watching the stars fade & noting some very dark clouds low in the sky, such a lovely quiet time of day. Rain is supposed to be arriving later this morning, quite a bit apparently. If not, I’ll be watering later.
    Anyway I’m up, I’ve had tea, toast & coffee. That’s all I’ve done though. I intend to do yin yoga class soon I feel in the need of some gentle exercise. Then as it’s Sunday I’ll be off to visit my sister. I’m supposed to be going out for a family dinner this evening but at the moment I’m thinking I might beg off as I’m not in the mood. I’ll see how the day progresses.
    Hope you all enjoy your #Sunday whatever you’re up to 🌻. #EarlyMorning #Exercise #Family.

  7. Well That’s Nicely Packaged

    By Cliff Potts, CSO, and Editor-in-Chief of WPS News

    Baybay City, Leyte, Philippines — 25 October 2026, 17:35

    A Thoughtful Presentation

    At a certain point, the platform begins to present information in a particularly tidy manner. Headlines are shortened. Images are cropped just so. Context is compressed into something quick and consumable.

    Everything looks clean. Orderly. Easy to take in at a glance.

    On Simplifying the Message

    Nuance is trimmed for convenience. Longer explanations are unnecessary when the essence can be delivered immediately. The important part is that the message arrives intact, even if some details are left behind.

    After all, attention is precious. Brevity is a kindness.

    Ready for Sharing

    The packaged item is designed to travel. A click, a reaction, a repost. No additional thought required.

    Interpretation is optional. The presentation does most of the work.

    A Mild Observation

    In polite conversation, one usually allows space for explanation before drawing conclusions. A summary would not replace the discussion itself.

    But bless their heart, they do like to keep things simple.

    #contentPackaging #digitalEtiquette #Facebook #headlines #informationDesign #SocialMedia #WPSNews
  8. 🆕 Single Jungle 🎙️Et si le secret de l’ #amour durable était de ne pas vivre ensemble ? Avec Amandine Paoli (Ép.138), « Le Céli-#couple : quand l’amour a deux adresses » singlejungle.lepodcast.fr/et-s Amandine est célibataire, à 48 ans, ça ne lui était pas arrivé depuis ses 16 ans. Elle propose une autre vision de la relation amoureuse : sortir du schéma classique, qu’il soit hétéro ou LGBTQIA+. Qui a dit qu’on était obligé•e de vivre avec la personne qu’on aime ? Même quand le bébé arrive. #podcast

  9. I love the modern economy, then convenience, then never having to go to a local store.

    I need an $8 bottle brush:

    Mon, Oct 19 6:08pm Accepted at USPS Facility SANDUSKY, OH 44870
    woot!

    Tue, Oct 20 2:00pm Departed USPS Facility AKRON OH DISTRIBUTION CENTER, 44309
    here it comes!

    Thu, Oct 22 2:50am Departed USPS Facility DENVER CO DISTRIBUTION CENTER
    halfway here!

    Thu, Oct 22 11:34pm Arrived at USPS Facility SACRAMENTO CA DISTRIBUTION CENTER
    20 miles to go!

    Sat, Oct 24 6:03am Arrived at USPS Facility INDIANAPOLIS IN DISTRIBUTION CENTER
    aw... fuck. COME ON!

    #EBAY #FAIL
  10. Why 10,000 Steps a Day? The Curious Story Behind a Number We Took as Gospel

    Ten thousand steps became a famous fitness goal, but the science behind the number is more interesting than you might think.

    Dear Cherubs, why are we all chasing 10,000 steps a day as though a tiny digital counter holds the secret to eternal youth? The surprising answer takes us back to 1960s Japan, a clever marketing campaign and a number that may have become a health obsession partly because a machine reset at 10,000.

    THE NUMBER THAT SOLD A WALKING HABIT

    According to The BMJ, the familiar target traces back to Japan in the mid-1960s, when a company called Yamasa introduced a pedometer known as the manpo-kei. The name translates roughly as “10,000-step meter”, and it arrived during the excitement surrounding the 1964 Tokyo Olympics.

    The timing was excellent. Japan was becoming increasingly interested in physical fitness, and the idea of tracking daily movement offered people a simple way to get more active. Ten thousand was memorable, easy to communicate and satisfyingly round. Marketing departments have been exploiting those qualities for decades. No surprises there.

    But here comes the interesting bit. Research published in the journal Ethnographiques.org reports that the original manpo-kei reset to zero after every 10,000 steps. That detail gives the machine-reset theory some credibility: a device designed around a particular number could have helped reinforce that number as a daily target.

    However, it would be a stretch to claim that the reset mechanism alone created the trend. The product was already named after 10,000 steps, and the slogan was being promoted as a walking goal. The evidence points to a combination of marketing, product design and a catchy number rather than one mechanical quirk changing humanity forever.

    A MARKETING NUMBER BECOMES A HEALTH RULE

    The real plot twist is that 10,000 steps was not originally established through clinical trials proving that this exact number was necessary for good health. The scientific evidence came later, while the target had already gained popularity.

    According to The BMJ, the figure became widely recognised through the Japanese campaign rather than emerging from a scientific discovery. Over time, pedometers, fitness trackers, smartphones and workplace challenges helped turn it into a familiar benchmark.

    And it stuck. There is something wonderfully human about preferring a clear target to a complicated explanation. Ten thousand feels like a mission. Six thousand feels like an unfinished spreadsheet.

    Does that mean walking 10,000 steps is pointless? Absolutely not. Walking regularly supports health, and increasing activity can be beneficial, particularly for people who spend much of the day sitting. The problem is treating one round number as a universal medical requirement.

    Research published in JAMA Internal Medicine in 2019 found that, among older women studied, taking around 4,400 steps daily was associated with a lower risk of death than taking around 2,700. The association levelled off at approximately 7,500 steps in that study. Results from one group do not establish the perfect target for everyone, but they show that meaningful benefits can occur below 10,000.

    The takeaway? Aim to move more, build a routine you can maintain and adapt your goals to your circumstances. Missing an arbitrary number on your watch is not a moral failure.

    For more curious explainers about everyday myths and surprising facts, explore Thisclaimer at thisclaimer.com and its YouTube channel. Because sometimes the real story behind a modern habit is far more interesting than the habit itself.

    Sources

    The BMJ — “Sixty seconds on… 10 000 steps” — https://www.bmj.com/content/384/bmj.q598

    Ethnographiques.org — “Taking 10,000 steps a day – really? A survey of ordinary self-tracking practices” — https://shs.cairn.info/article/E_RES_216_0157/pdf?lang=en

    Cairn.info

    JAMA Internal Medicine — “Association of Step Volume and Intensity With All-Cause Mortality in Older Women” — https://jamanetwork.com/journals/jamainternalmedicine/fullarticle/2734709

    Step Counting: A Review of Measurement Considerations and Health-Related Applications — https://pmc.ncbi.nlm.nih.gov/articles/PMC5488109/

    Thisclaimer — https://thisclaimer.com/

    Thisclaimer YouTube — https://www.youtube.com/@thisclaimer?sub_confirmation=1

    The Thisclaimer logo blends a classic warning symbol with a brain icon to represent critical thinking, curiosity, and thoughtful disclaimers #10000Steps #dailyExercise #fitnessMyths #fitnessTrackers #healthFacts #japaneseInventions #pedometerHistory #surprisingHistory #tokyoOlympics #walkingFacts
  11. Las normas invisibles que sostienen la convivencia en el fediverso

    Los buenos modales y el respeto mutuo como el verdadero motor para mantener comunidades unidas en una red sin dueños

    Entrar a una red social descentralizada como Mastodon puede desconcertar a cualquiera al principio porque las cosas funcionan de forma muy distinta a los canales comerciales tradicionales. En las plataformas privativas de las grandes corporaciones, un algoritmo diseñado para generar polémica nos empuja todo el tiempo a discutir, a engancharnos en peleas inútiles y a ver a quien piensa diferente como un enemigo al que hay que aplastar para ganar atención. En cambio, el entorno de las redes abiertas se construyó con otra mentalidad donde no hay un sistema buscando monetizar nuestro enojo ni premiando el conflicto. Sin embargo, para que este espacio funcione de forma sana sin un director general que imponga las reglas desde arriba, la propia comunidad ha tenido que desarrollar un conjunto de buenos modales y cortesía digital que conocemos de forma común como fediqueta.

    Esta etiqueta de convivencia no es un reglamento estricto con castigos legales, sino un acuerdo de camaradería y respeto para que personas con ideologías, creencias o gustos totalmente opuestos puedan compartir el mismo espacio en paz. Uno de los pilares de este comportamiento es entender que los servidores son hogares gestionados por personas que pagan los gastos de su propio bolsillo, por lo que entrar a debatir exige la misma educación que tendríamos al visitar una casa ajena. Eso implica aprender a escuchar, argumentar sin caer en insultos y aceptar que la diversidad de opiniones es parte natural del ecosistema. Herramientas sencillas como las advertencias de contenido se usan de manera cotidiana no para censurar, sino como un gesto de cortesía que permite al vecino elegir si quiere leer sobre un tema sensible o debatir de política en ese momento específico de su día.

    La cortesía en la red también se nota en detalles que facilitan la vida a los demás, tal el caso de que se acostumbra evitar el uso de etiquetas de forma masiva o el SPAM que ensucie las líneas de tiempo locales, cuidando que la conversación se mantenga genuina y cercana. Los servidores independientes ponen sus normas básicas de operación en sus páginas de inicio para evitar abusos o delitos, pero la verdadera salud del entorno depende de estos modales cotidianos que elegimos aplicar cada vez que interactuamos con alguien. Este concepto de comportamiento en internet tiene sus raíces directas en el documento RFC 1855, una guía oficial de netiqueta que se publicó de forma abierta en octubre de 1995.

    — A. Eldritch, Periodista, Locutor, podcaster y bloger del fediverso

    Alt text via @altbot y @TeLoDescribot

    #Fediqueta #Netiqueta #Fediverso #SoberaníaDigital #Convivencia #Mastodon #InternetLibre

  12. For years the main reason to add an FAQ section was the dropdown it could earn in Google results. That reason has gone. The page itself still matters, though, because AI assistants and AI search features pull short, direct answers from pages, and a well-built FAQ is one of the easiest things on a site for them to lift.

    This post covers what changed at Google, what still makes an FAQ worth writing, and the HTML pattern we use so each answer stands on its own.

    Disclosure: Appie.run publishes this post. The AI FAQ Generator and Website FAQ Generator mentioned below are our free tools. Everything else here works with any CMS and no tool at all.

    What Google changed (as read on 26 Oct 2026)


    From Google's Search Central updates and Search Console Help:

    • FAQ rich results stopped appearing in Google Search on 7 May 2026, and Google added a deprecation notice on 8 May.
    • On 15 June 2026 Google removed the FAQ structured data documentation, the FAQ report in Search Console and FAQ support in the Rich Results Test.
    • Search Console API support for FAQ appearance data was removed in August 2026.
    • Google says existing FAQPage markup can stay on your pages and causes no harm.
    • In the same June update Google noted that an llms.txt file isn't needed for Google Search.

    So: no more SERP dropdown, no penalty for leftover markup, and no special file required. What's left is the content.

    Why an FAQ is still worth writing


    Nobody outside the AI companies can tell you exactly how each assistant picks its sources, and we won't pretend to. What you can control is whether your answer is easy to find, easy to extract and correct when pulled out of context. A question-and-answer block does all three if you write it properly:

    • The question matches the way people actually ask it.
    • The first sentence of the answer is the answer.
    • The answer makes sense without the paragraphs around it.

    Those same properties help a human who lands on the page from a support link, so the work isn't wasted whichever way the traffic arrives.

    Step 1: Collect real questions


    Don't invent questions in a meeting. Pull them from places where customers already asked:

    • Support tickets and live chat transcripts
    • Sales call notes ("Does it work with...?", "What happens when...?")
    • Reddit and community threads in your category
    • Your site search logs

    Group duplicates, then keep the 8 to 15 that come up most or block a purchase.

    Step 2: Write answers that survive being quoted alone


    A quick test for each answer: paste it into a blank doc with only the question above it. Does it still make sense?

    Weak:

    Yes, as mentioned above, it does, depending on your plan.


    Better:

    Yes. Team plans include SSO via SAML. The Starter plan does not.


    Rules we follow:

    1. Answer in the first sentence. Yes/no, a number, or a name.
    2. Name the thing. Say "the Starter plan", not "this plan".
    3. Keep it to 40 to 80 words for most answers. Link out for detail.
    4. Date anything that changes. "As of 26 Oct 2026, the Starter plan costs $19/month." Prices and limits go stale, and a stale quoted answer is worse than none.
    5. Only state what the page can back up. If the policy lives elsewhere, link to it rather than paraphrasing it loosely.


    Step 3: Use plain, semantic HTML


    You don't need a plugin. Headings for questions and paragraphs for answers are enough, and they render the same for every crawler:

    <section id="faq" aria-labelledby="faq-title">
    <h2 id="faq-title">Frequently asked questions</h2>

    <h3 id="faq-sso">Does the Starter plan include SSO?</h3>
    <p>No. SSO via SAML is included on Team plans only. The Starter plan
    uses email and password sign-in. <a href="/pricing">Compare plans</a>.</p>

    <h3 id="faq-cancel">Can I cancel at any time?</h3>
    <p>Yes. You can cancel from the Billing page, and your plan stays active
    until the end of the current billing period.</p>
    </section>

    If you prefer collapsible answers, <details>/<summary> keeps the text in the HTML:

    <details>
    <summary>Can I cancel at any time?</summary>
    <p>Yes. You can cancel from the Billing page, and your plan stays active
    until the end of the current billing period.</p>
    </details>

    Avoid loading answers only via JavaScript after a click. If the text isn't in the served HTML, some crawlers will never see it.

    Give each question an id so you can link straight to it from support replies and docs.

    Step 4: Keep or add FAQPage markup (optional)


    Google no longer shows FAQ rich results, and it says leftover markup does no harm. Other consumers of schema.org data may still read it, so if it's already there, keep it in sync with the visible text. If you add it, mirror the on-page wording exactly:

    <script type="application/ld+json">
    {
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
    {
    "@type": "Question",
    "name": "Can I cancel at any time?",
    "acceptedAnswer": {
    "@type": "Answer",
    "text": "Yes. You can cancel from the Billing page, and your plan stays active until the end of the current billing period."
    }
    }
    ]
    }
    </script>

    The risk with markup is drift: someone updates the visible answer and forgets the JSON. If your FAQ comes from a CMS field, generate both from the same source.

    Step 5: Put the FAQ where the question is asked


    One giant /faq page is fine as an index, but the most useful placement is next to the thing in question: pricing questions on the pricing page, setup questions in the docs. A short block of 4 to 6 questions per page tends to stay accurate because the owner of that page sees it.

    Step 6: Review it on a schedule


    Add a "last reviewed" date and put a recurring reminder on someone's calendar. Every price, limit and integration claim in the FAQ should be checked against the product at least each quarter.

    Getting a first draft faster


    If you have the source material but not the time, two of our free browser tools can produce a draft for you to edit (both run a captcha check first):

    • AI FAQ Generator (appie.run/tools/ai-faq-generator): paste up to 2,000 characters of text, pick 1 to 10 FAQs, a language and a tone. The answers are grounded in the text you pasted, and it doesn't add policies or prices that aren't there.
    • Website FAQ Generator (appie.run/tools/website-faq-generator): give it up to 5 public URLs. It skips questions it can't answer from those pages instead of guessing.

    Treat the output as a draft. Check every answer against Step 2's rules before it goes live.

    Checklist


    • [ ] Questions come from real customer sources
    • [ ] Each answer starts with the answer
    • [ ] Each answer makes sense on its own
    • [ ] Prices and limits carry an "as of" date
    • [ ] Questions and answers are in the served HTML
    • [ ] Any FAQPage JSON-LD matches the visible text word for word
    • [ ] A review date is set

    Google sources: Search Central blog and Search Console Help pages on FAQ rich results and structured data, read 26 Oct 2026.

    RG, Founder, Appie.run#seo #html #webdev #ai #software #coding #development #engineering #inclusive #community
    How to Write a Website FAQ That AI Answers Can Quote (Now That Google's FAQ Rich Results Are Gone)

  13. Quick Answer


    A fleet tracking backend should treat every GPS ping as untrusted input. Sort pings by device time, drop duplicates and impossible values, reject poor fixes and teleport jumps, hold position while a vehicle is parked, and add hysteresis to geofences. Keep the raw stream, store the cleaned stream beside it, and snap to roads only after cleaning. The Python below was tested on synthetic data only, not on live device feeds.

    Why does a fleet app receive bad GPS data?


    Some of the reasons are written down in vendor documentation. Samsara's vehicle locations documentation says a device reports about every 5 seconds while the vehicle is on and about once an hour while it is off. It also says identical consecutive records can occur, and that GPS interference in a garage can suppress updates even when the vehicle shows as on. The same page says the device keeps a rolling 30 days of location data, so after a connection is restored the buffered points become available through the API.

    Read together, those statements describe four problems a backend must expect: duplicate rows, silent gaps, a misleading "on" status, and late data that arrives out of order. This is one vendor's documentation. Other vendors will behave differently, so read the equivalent page for the device you actually use.

    What should the ingest layer check before it stores a ping?


    My suggestion (author judgement, not a standard) is six cheap checks, run in this order:

    1. Sort by device timestamp, so late arrivals land in the right place.
    2. Drop exact duplicates (same time and position).
    3. Reject impossible values, including out-of-range coordinates and the 0,0 position that some receivers report before they have a fix.
    4. Reject poor fixes, where the reported accuracy is worse than a threshold.
    5. Reject teleport jumps, where the implied speed between two kept points is not plausible for a vehicle.
    6. Hold position while parked, so receiver jitter does not draw a wandering trail.

    The thresholds in the code (50 m accuracy, 45 m/s, 10 m jitter) are starting values I chose for the example. Tune them against your own vehicles and devices.

    from dataclasses import dataclass
    from math import radians, sin, cos, asin, sqrt

    @dataclass(frozen=True)
    class Ping:
    device: str
    ts: int # epoch seconds, device clock
    lat: float
    lon: float
    acc_m: float = 10 # reported horizontal accuracy in metres

    def haversine_m(a, b):
    r = 6371000.0
    p1, p2 = radians(a.lat), radians(b.lat)
    dp, dl = p2 - p1, radians(b.lon - a.lon)
    h = sin(dp / 2) ** 2 + cos(p1) * cos(p2) * sin(dl / 2) ** 2
    return 2 * r * asin(sqrt(h))

    def clean(pings, max_acc_m=50, max_speed_ms=45, jitter_m=10):
    """Return a cleaned, time-ordered list for ONE device."""
    seen, ordered = set(),
    [] for p in sorted(pings, key=lambda p: p.ts): # 1. fix ordering
    key = (p.ts, round(p.lat, 6), round(p.lon, 6))
    if key in seen: # 2. drop duplicates
    continue
    seen.add(key)
    if not (-90 <= p.lat <= 90 and -180 <= p.lon <= 180): # 3. impossible values
    continue
    if p.lat == 0 and p.lon == 0: # "null island" fix
    continue
    if p.acc_m > max_acc_m: # 4. poor fix
    continue
    ordered.append(p)

    out =
    [] for p in ordered:
    if out:
    prev, dt = out[-1], p.ts - out[-1].ts
    if dt <= 0:
    continue
    d = haversine_m(prev, p)
    if d / dt > max_speed_ms: # 5. teleport jump
    continue
    if d < max(jitter_m, p.acc_m): # 6. parked jitter
    p = Ping(p.device, p.ts, prev.lat, prev.lon, p.acc_m)
    out.append(p)
    return out

    Testing status: I ran six unit tests with Python 3.13 on synthetic points: out-of-order input, duplicates, 0,0 and poor-accuracy points, a teleport jump, parked jitter, and geofence flapping. All six passed. I have not run this against real device feeds, so treat it as a teaching sample and not production code.

    How do you stop geofence alerts from flapping?


    A vehicle parked near the edge of a depot boundary can cross it back and forth because of receiver noise, and each crossing can fire an alert. Two techniques help. Use hysteresis, which means the vehicle enters a zone inside radius r but only exits beyond r plus a buffer. Then require several consecutive pings before the state changes.

    class Geofence:
    """Circle fence with hysteresis: enter inside r, exit only outside r + buffer."""
    def __init__(self, lat, lon, r_m, buffer_m=30, confirm=2):
    self.c = Ping("fence", 0, lat, lon)
    self.r, self.buf, self.confirm = r_m, buffer_m, confirm
    self.inside, self._streak = False, 0

    def update(self, p):
    d = haversine_m(self.c, p)
    want_inside = d <= self.r if not self.inside else d <= self.r + self.buf
    if want_inside == self.inside:
    self._streak = 0
    return None
    self._streak += 1
    if self._streak >= self.confirm:
    self.inside, self._streak = want_inside, 0
    return "enter" if self.inside else "exit"
    return None

    In the test, a sequence of distances of 150, 90, 95, 110, 98, 105, 160 and 170 metres from a 100 m fence produced exactly one enter event and one exit event. Two of those readings (110 m and 105 m) were outside the 100 m radius while the vehicle was still inside the zone, and the buffer absorbed both.

    Should you snap points to roads?


    Map matching can clean what the filters above leave behind, but it has its own rules. Google's Roads API documentation says one snap-to-roads request accepts up to 100 GPS points and returns points snapped to the most likely road. It recommends keeping consecutive points at or below about 300 metres apart, and offers an optional interpolate setting that adds points following the road shape. Interpolated points have no original index, so the response can contain more points than the request.

    OSRM's Match service takes optional timestamps, which must increase, and optional per-point radiuses that default to 5 metres. The documentation suggests using the device's reported accuracy. It returns null for points dropped as outliers and a confidence score from 0 to 1 for each matching. The OSRM page I read was for version 5.5.1, so check the documentation for the version you run.

    My judgement: snap after cleaning, keep the raw point and the snapped point side by side, and treat a low confidence score as a flag for review rather than an error.

    How do you find vehicles near a depot quickly?


    PostGIS documents ST_DWithin as a cheap filter that can use a spatial index, while ST_Distance computes exact distances and cannot use indexes. For geography values the distance is in metres. The common pattern is to filter with ST_DWithin first and sort with ST_Distance on what remains.

    SELECT v.id, ST_Distance(v.last_position, d.location) AS metres
    FROM vehicles v
    JOIN depots d ON d.id = 7
    WHERE ST_DWithin(v.last_position, d.location, 2000)
    ORDER BY metres;

    This query is untested. It assumes both columns are geography with a spatial index on last_position, so check the types and the index in your own schema.

    What should the fleet database store?


    In my view three tables cover most needs: an append-only table of raw pings, a table of cleaned pings that maps and reports read, and a small table holding the last known position per vehicle for proximity queries. Keeping the raw data lets you re-run a better filter later and settle disputes about a route.

    Which are the top five fleet management app development companies?


    Teams that prefer to buy this work instead of building it can compare the five partners below. The list is not a ranking of quality.

    Figures below come from each company's own website and are self-reported, so confirm them directly before signing anything.

    1. Dev Technosys


    Dev Technosys is a fleet management app development company with 250+ professionals that does business globally. Its fleet page describes connecting GPS tracking, fuel monitoring and dispatching systems, then automating assignments, maintenance alerts and journey updates. The company builds its own platforms and connects them to existing business systems through APIs instead of configuring third-party ERP products. It states an 89% project success rate and says most new business comes through client referrals; both claims are self-reported. That scope fits teams that already own tracking hardware and need workflow software around it.

    2. N-iX


    N-iX lists fleet management software development as a dedicated service. Its page covers telematics and predictive-maintenance integration, ELD and IoT sensor integration, hours-of-service compliance modules, route-planning and dispatch engines, and mobile fleet apps. A case study describes a GPS-tracked in-vehicle Linux gateway, a Google Cloud IoT platform and an Android driver app for a telematics client, in a partnership that began in February 2021. The site states over 2,400 software engineers, and the case study gives no fleet outcome figures. N-iX suits teams that need hardware-to-cloud telematics work from one vendor.

    3. Intellias


    Two fleet case studies sit on the Intellias site. In the first, a Florida telematics client has worked with the company since 2018 on a platform with real-time GPS mapping, idle-time tracking and diagnostic trouble code reporting, and the page says it handles 100,000+ vehicles with data points every 30 seconds. The second is a native iOS, Android and Angular truck-tracking front end for a large car maker, tested on 1,000 vehicles and offered in more than 20 countries. Intellias suits teams that expect high vehicle counts and need a backend built for that volume.

    4. Altoros


    Altoros says it was founded in 2001 and lists GPS tracking software for car rental, trucking and delivery, fleet management with vehicle tracking and dispatch, and IoT platforms for fleets. Its logistics page cites a transport management case serving 100+ companies and processing 10,000+ automated orders a day, with operator workload cut by up to 70%, plus a truck-parking app prototype covering 10,000+ locations. All of these figures are self-reported, and the page names no ISO certification, so ask for evidence. Altoros suits teams that want an IoT-heavy build from a long-established vendor.

    5. STX Next


    Describing itself as a Python-native team with more than 20 years of experience, STX Next lists fleet management systems, route optimization, electronic proof of delivery, predictive maintenance and IoT integration on its transport and logistics page. Named case studies include Sendcloud (a carrier integration proof of concept), GS1 Polska (a location-data app for drivers) and T Dispatch (dispatch software). The page mentions Python, IoT, RFID, AWS, Azure and Snowflake and lists delivery centers in Poznan and Merida, but it states no headcount. STX Next suits teams that prefer a Python backend.

    FAQ


    How often should a fleet device send a position?

    Samsara's documentation describes about every 5 seconds while a vehicle is on and about hourly while it is off. Your hardware and data plan set the real figure.

    Should raw pings be deleted after cleaning?

    In my view, no. Keep them for a retention period your own policy allows, so you can re-run improved filters later.

    Do I need map matching in every fleet app?

    No. Many dashboards work with cleaned points. Matching helps most when you report distance driven on roads.

    What accuracy threshold should I use?

    The example uses 50 m as a starting value. Tune it per vehicle type and device.

    Can I use this code in production?

    It is a teaching sample tested on synthetic data. Add tests built from real device samples first.#python #backend #iot #architecture #software #coding #development #engineering #inclusive #community
    Designing a Fleet Tracking Backend That Handles Bad GPS Data

  14. Second Death

    Hi everyone! I hope you’re all well. Today, I thought I’d share a little horror short that I wrote a while ago and couldn’t decide what to do with. I hope you enjoy it!

    Second Death

    He felt the spark of consciousness fill his mind. He was aware now.

    He tried to move but found that nothing worked; even the muscles that lifted his eyelids failed him. In fact, every muscle in his body was frozen. He was paralysed, though by what or how, he could not say.

    His mind was sluggish and foggy, his memory having all but failed entirely, depriving him of the knowledge of who or where he was, but leaving everything else. The only reasoning for his current situation that he could come up with was that he had been in some sort of terrible accident, perhaps having been run over by a horse and buggy, and was now lying on some bed in the London hospital, a poultice wrapped around his head. The streets were a mess with horses and buggies these days. He knew that, at least.

    The fact that his mind had woken before the rest of his body did not frighten him. He knew this sort of thing happened every day in London; people being brought to the hospital in all manner of conscious states, and since he felt no pain, he was certain that somebody was taking very good care of him indeed.

    As he lay there, waiting for his body to catch up with his brain, some vestigial ember, a flicker of activity deep inside his mind, sparked, sending images rushing to the fore. A jumble of faces accosted him as his memory began to slowly filter through the abstract dam that had thus far held it back; women in long grey dresses with white aprons and white caps, and men, some old and bearded, some young and clean-shaven, but all wearing dark clothes. Somehow, he knew they were doctors and nurses.

    However, since waking up, he had heard no doctors or nurses—nor anybody else for that matter—coming to check on him. Had he been forgotten? Had they left him alone, thinking that he might never wake? His heart began to quicken at the thought that he might actually be stuck like this forever, that he might be trapped inside the confines of his own mind, his own mental walls slowly closing in on him. Surely, he would begin to disappear into insanity.

    The thought of being left in his current state until his body died of starvation and dehydration filled him with anxiety. He had to wake up. He had to force his mind and body to work in unison once more. He had to move, somehow; his very survival depended on it.

    Forcing his mind to work harder, he saw flashes of whitewashed walls and long, narrow corridors, and at first, he thought perhaps he might have been conscious upon his arrival at the hospital. 

    As sensation began to return little by little to his muscles, it occurred to him rather suddenly that there was a lack of sound. For a brief moment, he considered the fact that he may have gone deaf; he had known it to happen with head injuries, although he didn’t know how he knew, but the sound of his own breath leaving his lungs quelled the fear instantly.

    He was further relieved when he began to wiggle his toes, and further still when his fingers began to twitch. With each passing moment and every twitching phalanx, he felt the fear of his being trapped inside of himself ebbing away.

    Straining, he tried to open his eyes. He felt his lids fluttering, but everything remained dark. As he tensed and released each muscle in his legs and arms, still unable to fully move them yet, he willed his eyelids to cooperate—but darkness remained absolute. He tried again, and again, panic surging as he considered that he may have gone blind; he knew this, too, could sometimes happen with head injuries and again, how he knew this eluded him.

    As his heart quickly became a bass drum inside his ribcage, threatening to burst out at any moment, adrenaline surged through his body, and he felt his spine twitch—he willed his body to sit up, but the most he could manage was a slight raising of his head. He tried to gather himself, taking a deep breath, and then tried again, straining against himself as he attempted to fully reconnect his mind with his body. Drawing on every ounce of strength he could muster, he tried again, straining, straining, straining and… yes… yes… and…

    He jerked upward and—SLAM! His forehead collided painfully with something solid. The impact caused a spark, and in an instant, everything came rushing back. He was Eliot Smith, a doctor at The London Hospital. The adrenaline had acted like coal being shovelled into a waiting empty furnace; his whole body was mobile now; he could move his arms, his hands. He reached up, frantically exploring the area around him.

    As he felt the silk lining, the unyielding wood. The truth slammed into him with cold brutality—he had been buried alive.

    Terror consumed him. He screamed and clawed desperately, tearing at the lining and wood until his fingers bled. He pounded, kicked, and screamed until he felt his heart burst painfully in his chest. And with one final gasp of horror, he fell silent again—this time, forever.

    The End.

    Thanks for reading, if you did. I appreciate your time, and I hope you enjoyed it!

    As ever, thanks for stopping by!

    Until next time,

    George

    © 2026 GLT

    #death #horror #horrorStory #shortStories #shortStory #stories #writing
  15. I wired up a free model endpoint last month. I sent one request. It returned 200 OK. I shipped the feature. Then the tool calls never happened. The endpoint accepted the request. It just ignored half of it. Sound familiar?

    Here is my question. What does a 200 actually prove? My answer: almost nothing about capabilities. It proves the transport worked. That is it.

    So I stopped trusting status codes and started probing the contract. This post is the FAQ I wish I had read first. It ends with a script you can run in about two minutes.

    Myth 1: A 200 means the model supports my feature


    The server can accept a tools array and silently ignore it. The model then answers in prose. No error. No warning. Your code sees a normal response and skips the branch. Is that a bug in the model? No. It is a bug in your assumption.

    The corrected model: support is a property of the endpoint, not of the model name. Probe it. Record it. Re-probe when anything changes.

    Myth 2: finish_reason is optional metadata


    It is the most important field in the response. length means the model ran out of output budget. Your answer looks fine and is probably cut in half. I have watched a parser happily eat a truncated JSON object.

    {"choices":[{"finish_reason":"length","message":{"content":"{\"items\": [1, 2, 3, 4"}}]}

    If you do not branch on finish_reason, you are parsing whatever bytes arrived. That is not a feature. That is a coin flip.

    Myth 3: Streaming and non-streaming are interchangeable


    They are two different code paths. In streaming, finish_reason arrives in the final chunk, not the first. Some servers only report token usage when you ask for it explicitly. Some omit it entirely.

    Ask yourself: does my client read the last event? Mine did not, for a week. I was logging None as the finish reason every single time.

    Myth 4: JSON mode means my schema


    It means valid JSON. It does not mean your keys. It does not mean your types. Validate every response against a schema before it touches business logic. Treat model output like user input, because that is what it is.

    Myth 5: Retries are always safe


    Retry a failed read, fine. Retry a tool call that already wrote a row, and now you have two rows. I learned this from a duplicate charge, not a blog post.

    Add an idempotency key your tool honors. Make the retry decision depend on the operation, not on the exception class.

    The artifact: a five-minute capability probe


    This script uses only the Python standard library. It assumes a chat-completions-shaped endpoint. Adjust the paths if yours differs.

    # probe_capabilities.py — smoke test only, not a benchmark
    import json, os, time, urllib.request, urllib.error, concurrent.futures as cf

    BASE = os.environ["BASE_URL"].rstrip("/")
    KEY = os.environ["API_KEY"]
    MODEL = os.environ["MODEL"]

    def call(payload, stream=False, timeout=60):
    req = urllib.request.Request(
    BASE + "/chat/completions",
    data=json.dumps(payload).encode(),
    headers={"Content-Type": "application/json",
    "Authorization": f"Bearer {KEY}",
    "Accept": "text/event-stream" if stream else "application/json"},
    method="POST")
    t0 = time.time()
    try:
    with urllib.request.urlopen(req, timeout=timeout) as r:
    return {"status": r.status, "ms": int((time.time()-t0)*1000),
    "raw": r.read().decode("utf-8", "replace")}
    except urllib.error.HTTPError as e:
    return {"status": e.code, "ms": int((time.time()-t0)*1000),
    "raw": e.read().decode("utf-8", "replace")}

    def probe_truncation():
    p = {"model": MODEL, "max_tokens": 8,
    "messages": [{"role": "user", "content": "List ten colors."}]}
    r = call(p)
    if r["status"] != 200:
    return {"probe": "truncation", "ok": False, "why": r["status"]}
    ch = json.loads(r["raw"])["choices"]
    [0] return {"probe": "truncation", "ok": True,
    "finish_reason": ch.get("finish_reason"),
    "reports_usage": "usage" in json.loads(r["raw"])}

    def probe_tools():
    p = {"model": MODEL, "max_tokens": 128,
    "messages": [{"role": "user", "content": "Read ./README.md and report its first line."}],
    "tools": [{"type": "function", "function": {
    "name": "read_file",
    "description": "Read a file from disk.",
    "parameters": {"type": "object",
    "properties": {"path": {"type": "string"}},
    "required": ["path"]}}}]}
    r = call(p)
    if r["status"] != 200:
    return {"probe": "tools", "ok": False, "why": r["status"]}
    msg = json.loads(r["raw"])["choices"][0]["message"]
    return {"probe": "tools", "ok": True,
    "returned_tool_calls": bool(msg.get("tool_calls"))}

    def probe_json():
    p = {"model": MODEL, "max_tokens": 128,
    "messages": [{"role": "user",
    "content": 'Reply with only JSON: {"status":"ok","count":3}'}]}
    r = call(p)
    if r["status"] != 200:
    return {"probe": "json", "ok": False, "why": r["status"]}
    text = json.loads(r["raw"])["choices"][0]["message"]["content"]
    try:
    obj = json.loads(text)
    return {"probe": "json", "ok": True,
    "keys_match": sorted(obj) == ["count", "status"]}
    except json.JSONDecodeError:
    return {"probe": "json", "ok": True, "keys_match": False,
    "note": "not parseable as JSON"}

    def probe_concurrency(n=2):
    p = {"model": MODEL, "max_tokens": 16,
    "messages": [{"role": "user", "content": "Say ok."}]}
    with cf.ThreadPoolExecutor(max_workers=n) as ex:
    codes = list(ex.map(lambda _: call(p)["status"], range(n)))
    return {"probe": "concurrency", "ok": True, "statuses": codes,
    "saw_429": 429 in codes}

    if __name__ == "__main__":
    for fn in (probe_truncation, probe_tools, probe_json, probe_concurrency):
    print(json.dumps(fn(), sort_keys=True))

    Run it like this. Keep the key in the environment, never in the file.

    export BASE_URL="$YOUR_ENDPOINT"
    export API_KEY="$YOUR_KEY"
    export MODEL="$YOUR_MODEL"
    python3 probe_capabilities.py

    Reading the output: a decision table

    Probe resultWhat it meansWhat I do nextreturned_tool_calls: falseTools accepted, not acted onDrop the agent branch, or change endpointfinish_reason: "length" on an 8-token capNormal, expectedKeep the check; raise budget in real callsfinish_reason: null in streamingClient is not reading the final eventFix the parser before anything elsereports_usage: falseNo token accounting from serverCount tokens client-side, or accept blind costkeys_match: falseValid JSON, wrong shapeAdd schema validation at the boundarysaw_429: true at n=2Very low concurrency ceilingQueue work; never fan out blindly


    Nothing here measures quality. Nothing here measures speed. Those are different experiments with different controls.

    Where I run this


    I run probes from a throwaway box, not my laptop. Same reason I do not test migrations on my main database. The probe should not touch anything I care about.

    MonkeyCode's free model access and free server option are the two pieces I use for that. The free model access gives the probe something to talk to. The free server option gives it a disposable place to run. Disclosure: This article was prepared as part of MonkeyCode's product outreach.

    I am not claiming the free tier is fast, generous, or permanent. I do not know its limits, and I am not going to guess at them. Run the concurrency probe and read your own numbers. That is the whole point of this post.

    Limitations and who should skip this


    • This is a smoke test. It is not a benchmark and not a load test.
    • Results describe one endpoint, one model, one moment. They expire.
    • Paid tiers can behave differently from free ones. Re-probe after switching.
    • Only probe endpoints you own or are authorized to test.
    • Do not use this to grade answer quality. It checks contract shape only.

    Skip this approach if you need contractual latency SLOs, deterministic output, or guaranteed tool-call behavior. Buy a plan with a written contract. A probe will not save you from a missing SLA.

    The corrected mental model


    Treat every free endpoint as a set of separate promises. Transport, truncation, tool calls, JSON shape, and concurrency are five different promises. A 200 only confirms the first one.

    Which promise broke on your last integration? I keep a one-page probe log per endpoint now. It has saved me two weekends so far.#ai #api #testing #python #software #coding #development #engineering #inclusive #community
    200 OK Proves Nothing About Tool Calls: A Free-Model Capability FAQ With a Probe

  16. Every engineer running autonomous agent loops knows the in-context reflection drill. The agent runs a bash script, fails on an obscure permission flag or an unquoted path, sees the error in stderr, reflects on what went wrong, and fixes it on the second try.

    The task finishes green. You log the run, close the thread, and move on.

    Tomorrow morning, the same agent hits the exact same edge case in a fresh session and makes the exact same mistake all over again.

    In-context reflection is a temporary patch. It burns context tokens, bloats the prompt across long tool sessions, and evaporates the millisecond the execution context clears. The traditional alternative, full-model fine-tuning, is a non-starter for everyday errors. Nobody is spinning up a multi-GPU training run every afternoon to update base weights, and doing so risks catastrophic forgetting across existing tool workflows.

    A research team from Princeton University and Meta FAIR just published a practical middle ground. In their paper, Don't Forget What You Just Learned: Self-Directed Repair Turns Agent Mistakes Into Lasting Lessons (arXiv:2610.31846), Yuval Kansal, Karen Ullrich, Polina Kirichenko, Ilia Kulikov, Niraj K. Jha, Mohammad Pezeshki, and Mark Ibrahim lay out an architecture called Self-Direction.

    Instead of writing a reflection note into a scratchpad file or relying on a fragile system prompt append, the agent distills its execution mistakes directly into tiny low-rank adapter weights.

    The failure of the reflection scratchpad


    Modern agent setups usually address cross-session memory with one of two patterns:

    1. Appending error reflections to an agent scratchpad or MEMORY.md file.
    2. Embedding failure traces into a vector database for retrieval-augmented prompt injection on future turns.

    Both patterns struggle in production. Text notes appended to context eat away at attention budgets. As the reflection scratchpad grows, agents suffer from prompt dilution and instruction drift. More critically, an agent reading a natural-language description of an old error frequently misapplies the lesson to unrelated tool calls.

    The Princeton and Meta team tracked this failure mode across open-ended research workflows (GAIA), multi-step tool execution (Claw-Eval), and command-line environments (Terminal-Bench 2.1). When agents relied on standard in-context retries, their correction reliability plummeted when facing recurring variations of the same underlying task. The agent repeatedly fell into the same traps because the underlying policy distribution never moved.

    Standard Agent Flow:
    Error -> In-context reflection -> One-off fix -> Session ends -> Lesson lost

    Self-Direction Flow:
    Error -> Trajectory reflection -> Low-rank adapter update -> Persistent library -> Routed on demand

    Distilling mistakes into 0.02% parameter budgets


    The core mechanism of Self-Direction sits between ephemeral prompt engineering and heavy offline training.

    When an agent fails an execution trajectory, it runs an internal critique to isolate the decision step that caused the downstream failure. Once the corrective trajectory is verified, the system does not just print the correction. It freezes the base model weights entirely and trains a micro-LoRA adapter on the self-directed repair pair.

    The parameters updated during this step represent roughly 0.02% of the base model's parameter count.

    Because base weights remain frozen:

    1. Existing base model capabilities and general conversational skills stay intact without degradation.
    2. Training completes locally in seconds on consumer hardware without cluster coordination.
    3. The resulting adapter file is lightweight enough to store, version, and swap on the fly.

    The agent saves these targeted adapter checkpoints into a persistent local library. When a new prompt arrives, an automated routing layer inspects the problem context and attaches the relevant adapter before the execution loop begins.

    Benchmark gains across open-ended tasks


    The researchers tested Self-Direction on open-weight models from the Qwen family across three distinct agent benchmarks:

    • GAIA: Multi-modal, complex multi-hop research requiring web navigation and reasoning.
    • Claw-Eval: Structured tool-use workflows testing API interactions and parameter extraction.
    • Terminal-Bench 2.1: Unconstrained Linux command-line tasks, bash scripts, and system administration.

    Across these environments, adding Self-Direction improved overall task completion rates by 8.9 to 17.0 percentage points compared to standard in-context reflection baselines.

    More importantly, the recurrence rate of known errors dropped sharply. The authors found that Self-Direction nearly doubled the reliability of corrective actions on subsequent encounters. Instead of guessing whether the agent would notice a text hint in its system prompt, the updated adapter shifted the token sampling probabilities directly away from the faulty API syntax.

    The team also evaluated out-of-distribution transfer. A small set of adapters trained on specific terminal failures generalized across dozens of unseen tasks involving related file-system permissions and process management. The agent learned the structural pattern of the fix rather than memorizing the exact shell string.

    What this means for local agent runners


    For developers building and hosting agent infrastructure, this work highlights an architectural transition.

    Over the past two years, the industry leaned heavily on prompt stuffing to simulate agent learning. We treated context windows as infinite scratchpads, piling up few-shot examples, dynamic rules, and post-mortem notes until the prompt became brittle.

    Self-Direction shows that treating execution errors as online distillation targets produces cleaner long-term behavior. When an agent trips on an environment quirk, the solution is not to explain the error back to the model in prose every time it wakes up. The solution is to let the agent compile the lesson into weights, index the adapter, and move forward.#ai #agents #python #opensource #software #coding #development #engineering #inclusive #community
    Why In-Context Corrections Do Not Stick in Agent Loops

  17. I’m building EatNeat, a mobile app that helps people turn a nutrition plan into a manageable routine—before “What should I eat?” takes over the evening.

    A lot of meal-planning tools focus on creating a plan. I’m focused on what comes after: remembering it, finding something practical when hunger clocks in, and tracking what you ate without turning dinner into a spreadsheet assignment.

    EatNeat is still a prototype. Here’s what’s working, what I’m figuring out, and how the mascot Bitey provides moral support.

    The core loop


    The app is organized around a simple cycle:

    1. Create a meal plan or bring in an existing one.
    2. See the day’s meals and get reminders at their scheduled times.
    3. Browse meal ideas that match selected constraints.
    4. Capture or mark a meal as eaten.
    5. Review progress over the day and across recent days.

    The Today screen brings schedule and progress together. Meals can be marked eaten when their scheduled time arrives, and progress includes estimated nutrition metrics. The user stays in control; the app helps without handing out gold stars for lunch.

    AI as a helper, not the whole app

    EatNeat has AI-assisted flows for personalized plans, meal recommendations, recipes, and optional photos. Requests include selected filters and nutrition targets. Practical constraints are requirements: an “under 15 minutes” meal can’t hide a 40-minute oven step, and equipment filters should match the actual cooking method.

    Food photos are optional and handled separately from meal text. Without a photo, the meal still appears with a bundled animation or illustration. The recipe shouldn’t vanish because its glamour shot is late.

    The app can call configured service endpoints. During local development, some AI flows can call Gemini directly with a development environment key. A production app should route requests through an authenticated server and keep provider keys off the client.

    AI nutrition values are estimates. EatNeat is not a medical tool, and the prototype does not treat a missed meal as a failure or make clinical recommendations.

    Local-first state and reminders


    Plans and meal logs are stored on-device with AsyncStorage. Writes are debounced and serialized, and local notifications remind users at planned meal times—because remembering breakfast shouldn’t require remembering to remember breakfast.

    Private meal-log photos stay on-device. If a user uploads a plan photo for parsing, it goes to the configured plan-reading service, with that made clear before upload.

    The stack


    The current app uses:

    • Expo and React Native for the mobile app
    • Expo Router for file-based navigation
    • TypeScript for app screens, state, services, and UI components
    • React Native Paper for a small set of interface components
    • Reanimated for navigation and interface motion
    • AsyncStorage for local plan and log persistence
    • Expo Notifications for scheduled meal reminders


    What is still a prototype


    The accountability feed displays sample posts and does not publish to a social service. Some preview screens use illustrative nutrition data. The app doesn’t ship a backend, so server-based AI features need a configured endpoint. For now, the social circle is supportive and fictional.

    I’m also breaking larger screens into focused components. The Today screen’s progress visualization and schedule calculations now live outside its route file, making the daily flow easier to evolve.

    What I’m learning


    The most useful decision so far: keep the basic habit loop independent of AI. Meal ideas work without generated photos; logging works without image analysis; plans can be reviewed when a service is down. A flaky model shouldn’t get veto power over lunch.

    AI can add convenience, but a slow request or missing key shouldn’t block the everyday action. The meal still exists even if the pixels don’t.

    EatNeat is under active development. I’m currently refining the meal flow, reminders, and progress UI while building toward a more complete, privacy-conscious backend.

    If you’re building a habit-focused app, I’d love to hear how you decide which parts should depend on AI and which should keep working on their own.#buildinpublic #mobile #showdev #software #coding #development #engineering #inclusive #community
    # Building EatNeat: Meal Plans, Gentle Reminders, and a Supportive Mascot

  18. 4/5 #Auspol #GodAndDemocracy

    “They had a similar background and outlook in other ways, too, including their north-western Sydney upbringing and a small-business mindset.”
    That involvement has continued to the present day, with current federal Liberal leader Angus Taylor regularly praising the Brethren and calling out one of the church’s charities, the Rapid Relief Team, for its work in the community.
    Reflecting on John Howard’s involvement with the Brethren over the course of his political career, a spokesman for the former prime minister tells The Saturday Paper that the characterisation of him in Bachelard’s book “is like a curate’s egg – it’s good in parts”.
    “Many of the economic views attributed to him only evolved over time. He has constantly said that he did not bring rigid ideologic attitudes with him into parliament,” the spokesman says.
    “Mr Howard adheres strongly to the view that individual Australians or groups are free to either offer or receive help from others during the course of election campaigns – provided all conduct is within the law.”
    In an opinion piece published in The Age and The Sydney Morning Herald earlier this month, former Western Australian Liberal senator Linda Reynolds revealed how in the final weeks of the campaign a senior party official asked her to meet two men described as small businesspeople wanting to help. She recognised them as Brethren members and said they were seeking confidential campaign information and individual logins to Feedback, the party’s voter-contact system, so they could phone voters from their own premises.
    Reynolds refused. While she was assured the party would “turn off” its involvement with the Brethren in Western Australia, she soon saw Brethren members arrive in growing numbers at pre-poll booths, briefed by people who weren’t part of the Liberal Party’s local campaign teams, making other volunteers feel uncomfortable and at times intimidated.

    Recommended for you
    When Reynolds raised her concerns in the party room, some colleagues accused her of religious discrimination, an attack line used repeatedly by Coalition members of the Joint Standing Committee on Electoral Matters as they tried to mitigate or deflect questions to Bruce and Gareth Hales and other witnesses during other public hearings.
    Even though Reynolds did not allege specific misconduct, she noted that the church’s submission to the committee inquiry denied coordinating its members while acknowledging the many Brethren volunteers “clearly were” coordinated.
    “So, if the church did not co-ordinate them, who did?” Reynolds wrote.

    According to another Liberal moderate from New South Wales, whenever the Liberal Party turns to the Brethren, it ends up backfiring.

    cont 5/5

  19. RT: @spycraft101 Canadian teenager Laken Pavan was arrested in Poland on espionage charges in May 2024.

    Laken joined the Canadian Armed Forces’ Bold Eagle cadet program at age 16 and trained as a combat engineer. But he soon felt unfulfilled with his military service and schooling and decided to go overseas to gain some new life experience.

    On April 15th, 2024, Laken asked to be excused from English class to go to the restroom and instead walked outside to begin a voyage to Ukraine. He took a ferry to Vancouver, flew by himself to Istanbul, and then on to Moscow. From there he traveled to Donetsk and joined a volunteer group called Interbrigade.

    After Interbrigade members realized he was only 17 years old, they planned to send him back home as soon as possible. He mostly spent the next few days in limbo but was detained by Russian FSB agents who’d learned of his presence. Over the course of a week, they interrogated him and then recruited him for operations in Europe.

    Laken traveled first to Copenhagen. He communicated with his handler “Slon” via Telegram and the Instagram account @astridjenson.dnk and received small payments in Bitcoin for his expenses. Slon told him to report any and all interesting connections with foreigners in the city, such as US military personnel on vacation. The initial plan was for him to reenter Ukraine and join a militia unit, while reporting back to the FSB.

    After a short period in Denmark, he moved to Warsaw, where he believed it would be easier to withdraw Bitcoin. But shortly after arriving he drunkenly confessed to a hotel worker and then to police that he was in Poland as a spy. He was immediately arrested, several weeks before his 18th birthday.

    Laken was convicted and sentenced to 20 months in prison. He spent his 18th and 19th birthdays in prison. In mid-August 2025 he was released and deported back to Vancouver.

    For episode 216 of the Spycraft 101 podcast I spoke to Laken about his journey to Ukraine, his recruitment by the FSB, his time in prison in Poland, and putting his life back together afterwards. The episode is available now.

    #fsb #warsaw #ukraine #vancouver #spy

  20. Most AI evaluation products check a sample of answers, after the answers have already gone out, without stopping anything. Read their documentation and you find all three properties written down as features.

    Mastra, a popular TypeScript agent framework, describes its scorers:

    "Live evaluations run in the background without blocking your agent responses or workflow execution."

    "The `sampling.rate` parameter (0-1) controls what fraction of outputs get scored."

    In the background. Not blocking. A fraction of outputs. Set the rate to 0.1 and nine answers in ten reach your user with no score at all. The tenth gets a score after the user has already read the answer.

    AWS offers online evaluation for agents on AgentCore, scored by language models acting as judges. The built-in judges come sealed:

    "Built-in evaluator configurations, including their evaluator models and prompt templates, cannot be modified."

    OpenAI's harness engineering team, writing in February 2026 about building a product with agents, stated the philosophy behind all of this more openly than anyone:

    "The repository operates with minimal blocking merge gates."

    "Test flakes are often addressed with follow-up runs rather than blocking progress indefinitely."

    "In a system where agent throughput far exceeds human attention, corrections are cheap, and waiting is expensive."

    I respect the candour, and for their case the trade holds. An internal product with fast rollbacks and engineers watching tolerates a bad merge. The cost of a wrong answer is one more pull request.

    Change the setting and the arithmetic flips. A financial reconciliation. A medical billing claim. A security review saying no issues found. A wrong answer there is not cheap to correct, because by the time a sampled, asynchronous score arrives, somebody already acted on the answer. A dashboard tells you yesterday's error rate. A dashboard does not stop today's error.

    So name what these tools are. Measurement. Good measurement, needed measurement. Not a gate. A gate sits between the answer and the reader, runs on every answer, and has the power to say no before anyone sees the answer.

    Merlin's checks on the final answer are gates in exactly this sense. They run on every answer, and they block before delivery. The rule counting open tasks runs on every proposed final answer, not on a tenth of them. A citation pointing into a file the run never read fails the task close, every time, before the answer exists.

    Blocking has a price, and I will not pretend otherwise. Our own gates have rejected correct work. In one run, our gate refused three correct Maven builds and one test run, each time with a message telling the model to run a build. The model concluded Maven was not installed, and the task closed without any build. A later post in this series covers the run, with the log. A wrong blocking gate is loud: you see the rejection, read the reason and fix the rule. A wrong sampled score is silent, and the answer already shipped.

    The question to ask any vendor selling you AI quality: on what fraction of answers does your check run, and does a failed check stop the answer. If the answers are "a sample" and "no," you bought a dashboard.#agents #ai #llm #softwareengineering #software #coding #development #engineering #inclusive #community
    Sampled, asynchronous, non-blocking

  21. Small coding choices can make software easier to understand and maintain. One example in C# is how we initialize string properties in DTOs.

    A DTO —Data Transfer Object— carries data between parts of an application. For example, it might carry a customer’s name from an API request into the application.

    Consider these two approaches:

    public sealed class CreateCustomerDtoWithNull
    {
    public string Name { get; init; } = null!;
    }
    public sealed class CreateCustomerDto
    {
    public string Name { get; init; } = string.Empty;
    }


    Both avoid the compiler warning about an uninitialized non-nullable property. Both initial values can be rejected by FluentValidation.

    But they create different starting states.

    For required text fields where missing and empty values are treated the same, I prefer string.Empty: it gives the property an actual string value without suppressing a compiler warning.

    The difference becomes clearer when we look at what each declaration means.

    With nullable reference types enabled, string expresses the intention that a property should not contain null.

    However:

    public string Name { get; init; } = null!;
    initializes that property with null.


    The ! suppresses the nullable warning. It does not create a value, check anything at runtime, or guarantee that something will replace the null later. Microsoft explicitly documents that the operator has no runtime effect. Microsoft: null-forgiving operator.

    With:

    public string Name { get; init; } = string.Empty;
    the property starts with "": an actual string containing zero characters. It is different from " ", which contains a space. Microsoft: String.Empty.


    This makes the initial state more consistent with the declared type. We have a string; we still need to check whether its content is acceptable.

    “FluentValidation can catch both” is correct.

    For example:

    using FluentValidation;
    public sealed class CreateCustomerDtoValidator
    : AbstractValidator
    {
    public CreateCustomerDtoValidator()
    {
    RuleFor(x => x.Name)
    .NotEmpty()
    .WithMessage("Name is required.");
    }
    }
    For strings, NotEmpty() rejects all of these:
    Value Result
    null Rejected
    "" Rejected
    " " Rejected
    "Maria" Accepted


    This behavior is documented by FluentValidation and can also be checked in its implementation. FluentValidation documentation, NotEmptyValidator source code.

    The preference for string.Empty therefore concerns the object’s starting state and the clarity of the code.

    It separates two responsibilities:

    • Initialization: give the property a non-null starting value.
    • Validation: decide whether the supplied content meets the requirements. A blank name is still invalid for creating a customer. Having a string value and having a valid customer name are different requirements.

    Also, validation does not fill in the missing name. It reports the problem so the application can reject the request.

    In an ASP.NET Core application using Clean Architecture, a straightforward execution flow is:

    API receives the request
    → DTO is created
    → Application validates the input
    → Domain creates a valid customer
    → Infrastructure saves the customer

    The Application layer can execute validation before continuing:

    await validator.ValidateAndThrowAsync(dto, cancellationToken);

    // Continue with customer creation only after validation succeeds.
    The API must then translate validation failures into an appropriate response, such as HTTP 400 with useful error messages.

    The Domain should also protect its own essential rules when creating a customer. This keeps those rules effective when data arrives through another route.

    Clean Architecture supports this separation of responsibilities. It does not prescribe a particular DTO initializer. Microsoft: common application architectures.

    For a manager, the practical benefit is straightforward: clear starting states reduce the assumptions developers need to make. Reviewers can see what the object initially contains and where unacceptable input is rejected.

    There are limits to this preference.

    First, string.Empty only sets the initial value. Depending on serializer settings, an incoming JSON value such as "name": null can replace it. External input still needs validation. Microsoft: nullable annotations in System.Text.Json.

    Second, sometimes null carries useful information. If a DTO should accurately represent missing input, a nullable property can be more appropriate:

    public string? Name { get; init; }

    The business rule can still require a name. The nullable type acknowledges that an incoming request may fail to provide one.

    There are other reasonable designs too. Maarten Balliauw discourages using default! to silence warnings in JSON DTOs and discusses alternatives such as nullable properties, constructors, and required. His article supports avoiding hidden assumptions, rather than a universal preference for empty strings. Maarten Balliauw: nullable warnings in JSON models.

    Ian Griffiths provides a useful counterargument: an empty string can also hide missing meaningful data if it is added simply to silence the compiler. This matters especially when objects are expected to be valid immediately after construction. Ian Griffiths: defeating the point with empty strings.

    My preferred team convention is therefore:
    For input DTOs where missing and empty text have the same meaning, use string.Empty and validate required content with NotEmpty(). Use nullable properties when absence matters. Use null! when there is a specific, justified initialization guarantee.

    The aim is to keep the declared intention, actual starting value, and validation rules consistent—and easy for the next person to understand.

    [email protected]#coding #csharp #dotnet #softwaredevelopment #software #development #engineering #inclusive #community
    Why I Prefer string.Empty Over null! in Input DTOs

  22. n8n: The 208k-Star Fair-Code Workflow Engine That Replaces Zapier — And What Actually Happens When Your Workflow Runs


    You've probably heard n8n called "open-source Zapier." That's true enough to be useful and wrong enough to be misleading. Zapier is a hosted product you rent. n8n is a Node.js application you run, point at your own database, and own end to end. No per-task metering. No vendor lock-in. A $5–10 VPS handles a surprising amount.

    But the marketing pitch isn't why engineers reach for it. The escape hatch is: the moment the visual builder runs out of road, you drop into a Code node and write real JavaScript (or Python). You never hit a wall you can't code your way through.

    What most developers never learn is what actually happens between clicking "Execute Workflow" and seeing those green checkmarks light up on the canvas. The orchestrator that schedules nodes, synchronizes multi-input joins, keeps runs cancelable, and emits lifecycle hooks lives in roughly 1,250 lines of TypeScript. Let's open it up.

    The Mental Model: A Stack, A Waiting Map, and One Loop


    When you hit execute, n8n doesn't spin up a thread per node. It builds a single serializable run object — IRunExecutionData — that carries everything: the in-flight stack of nodes waiting to run, a waiting map for partially satisfied inputs, metadata, and final results. This same object travels from the editor to the server, into the engine, optionally across a Redis queue to a worker process, and back.

    // Simplified shape of the live execution object
    interface IRunExecutionData {
    startData: { destinationNode?, runNodeFilter? };
    resultData: {
    runData: Record<string, ITaskData[]>; // per-node run history
    pinData: Record<string, INodeExecutionData[]>;
    lastNodeExecuted: string;
    error: ITaskData | null;
    };
    executionData: {
    nodeExecutionStack: IExecuteData[]; // the work list
    waitingExecution: Record<string, Record<number, INodeExecutionData[][]>>;
    waitingExecutionSource: Record<string, Record<number, ISourceData[][]>>;
    contextData: Record<string, any>;
    runtimeData: Record<string, any>;
    };
    }

    The engine (WorkflowExecute in packages/core/src/execution-engine/workflow-execute.ts) seeds nodeExecutionStack with the start node, then enters a loop that shifts the front entry, runs the node, records the result, and enqueues downstream nodes. That's it. No hidden thread pool. No magic graph walker. Just a stack and a waiting map.

    Execution Order: v0 (Breadth-First) vs v1 (Depth-First)


    The single most important setting in a workflow is executionOrder. It changes one line in the scheduler:

    const enqueueFn = workflow.settings.executionOrder === 'v1' ? 'unshift' : 'push';


    • v0 (push): New work goes to the tail. Older work runs first. The walk feels breadth-first — all siblings at depth 1 finish before depth 2 starts.
    • v1 (unshift): New work goes to the front. The current branch keeps running. The walk feels depth-first — you chase one path to the bottom before backtracking.

    This doesn't change the graph. It only changes scheduling. Sibling order in v1 still follows canvas position (top-left first), but only among ready siblings. The canvas is not the execution graph — it only shapes ordering where the scheduler has freedom.

    Multi-Input Joins: The Waiting Map


    A node with two inputs doesn't run when the first branch arrives. The engine parks partial data in waitingExecution[nodeName][runIndex] with per-input placeholders. As each upstream finishes, the engine fills its slot. Only when all required inputs are non-null does it enqueue the node.

    // Inside addNodeToBeExecuted (simplified)
    if (requiredInputs.every(input => waitingExecution[nodeName][runIndex][input] != null)) {
    // All inputs ready — enqueue the node
    enqueueFn(executeData);
    } else {
    // Park partial data, wait for the rest
    waitingExecution[nodeName][runIndex][inputIndex] = inputData;
    waitingExecutionSource[nodeName][runIndex][inputIndex] = sourceData;
    }

    After the main stack empties, a sweep pulls forward any waiting node that now has enough data — even if some optional inputs stayed empty. This means a join can complete after one branch dies early, while a node still missing required inputs stays parked.

    Empty Output Kills the Branch (Unless You Say Otherwise)


    If a node returns no data and doesn't enter waiting state, the branch ends. The scheduler adds no downstream work. Set alwaysOutputData: true on the node and the engine fabricates a single empty item to keep the branch alive — useful when downstream nodes must run regardless.

    Legacy v0 keeps one compatibility path: it can still wake a downstream node connected via a second or later main input even when the upstream output is empty.

    Cycles: Node State, Not Special Graph Logic


    The scheduler doesn't treat cycles specially. It keeps pulling from the front of the same list. A node loops only if it schedules more work for itself. SplitInBatchesV3 demonstrates the pattern:

    // Stores loop state in node context
    const loopState = this.getContext('node') || { index: 0, items: inputData };
    const batch = loopState.items.slice(loopState.index, loopState.index + batchSize);
    loopState.index += batchSize;
    this.setContext('node', loopState);

    if (loopState.index < loopState.items.length) {
    return { loop: batch }; // schedules another visit to this node
    }
    return { done: loopState.items }; // exits the cycle

    The loop guard in processRunExecutionData stops accidental repeats when the same node and run index return without progress.

    Queue Mode: Same Engine, Different Process


    In standalone mode, the main process executes workflows directly. In queue mode (EXECUTIONS_MODE=queue), the main process enqueues a job into Redis (BullMQ) and returns immediately. A worker process dequeues, reconstructs the same IRunExecutionData object, runs the exact same engine loop, and writes results back to PostgreSQL.

    ┌─────────────┐ Redis Queue ┌─────────────┐
    │ Main │ ──────────────────▶ │ Worker │
    │ (UI/API) │ enqueue job │ (executes) │
    └─────────────┘ └─────────────┘
    │ │
    │ PostgreSQL │
    └──────────────────▶◀────────────────┘
    shared state

    The main process serves the UI, REST API, and webhooks. Workers are stateless — scale them horizontally via HPA/KEDA based on queue depth. Dedicated webhook-processor pods handle high-throughput webhooks without blocking the main UI. Python/JavaScript code nodes run in isolated taskRunner sidecars (V8 isolates via isolated-vm for JS, separate processes for Python) with RPC over WebSocket.

    The Data Model: Items, Runs, and pairedItem


    n8n's data model has three layers:

    Level 1 — Item: INodeExecutionData — { json, binary?, pairedItem?, metadata?, evaluationData? }. Nodes receive and return arrays of items on each input/output. This is the unit of data flowing through the graph.

    Level 2 — Run: Each node execution appends one ITaskData to resultData.runData[nodeName]. The array index = runIndex. ITaskData records input source, output data, timing, status, metadata, error state. source points back to the previous node, output, and run that supplied the input.

    Level 3 — Execution Object: The IRunExecutionData bundles startData, resultData, and executionData (the live scheduling state). The same object carries both result and live machine state — that's how n8n hands an execution to a queue worker, pauses it at a Wait node, and resumes it later with history intact.

    pairedItem records lineage, not magic. An output item points back to one input item, or one input plus array position, or a list of links. The engine normalizes these as items move through the workflow. When WorkflowDataProxy resolves $node("HTTP Request").json in a downstream node, it walks this ancestry chain. Broken lookups surface as specific errors: missing upstream lineage, no route back to referenced node, multiple matches, pinned data short-circuiting the chain, invalid index, or intermediate node not yet run.

    AI Agents: Native, Not Bolted On


    Since the 2.0 line, n8n ships a LangChain-based agent runtime. The Agent node maintains conversation history in ChatMemory, calls language models for planning, executes tools based on model decisions, and accumulates results until goal completion. Tool calling uses the same execution engine — tools are just nodes with execute methods. Vector stores, MCP connectivity, and guardrails plug into the same architecture.

    Fair-Code, Not Open Source


    n8n uses the Sustainable Use License. You can self-host and modify freely for internal business use, including paid consulting building workflows for clients. What you can't do is rebrand and resell it as your own hosted SaaS. Files with .ee. in the path are Enterprise-licensed. For an indie dev or team running their own automations, you're completely fine — but check the current license page rather than trusting any blog post on the fine print.

    What This Means for You


    • No per-execution pricing: Run 10 or 10 million workflows on your $5 VPS.
    • Full observability: Every execution persists to your database. Open any run, see exactly what each node received and emitted, replay it.
    • Escape hatch: Code nodes run real JavaScript/Python with npm/pip access. HTTP Request node talks to anything with an endpoint.
    • AI-native: Build agents that call tools, use memory, query vector stores — all self-hosted.
    • Production architecture: Queue mode + PostgreSQL + Redis + S3 scales horizontally. The same engine runs in-process or distributed.


    The Takeaway


    n8n isn't "Zapier you host." It's a workflow engine with a visual authoring layer, a serializable execution model that survives process boundaries, a scheduler you can reason about, and an escape hatch to real code. The 208k stars aren't for the UI — they're for the fact that when the visual builder hits a limit, you don't file a feature request. You write the code.#opensource #automation #workflow #selfhosted #software #coding #development #engineering #inclusive #community
    n8n: The 208k-Star Fair-Code Workflow Engine That Replaces Zapier — And What Actually Happens When Your Workflow Runs

  23. “Justice is the first virtue of social institutions, as truth is of systems of thought… Each person possesses an inviolability founded on justice that even the welfare of society as a whole cannot override.”*…

    Jacques-Louis David, The Tennis Court Oath, 1790-4 (source)

    Stephen Colbert once observed that “reality has a well-known liberal bias.” And indeed, liberalism— the political/moral philosophy rooted in individual liberty, consent of the governed, and equality before the law– has been a major ideology through modern times… and, of course, the major ideology animating the founding of the United States.

    But as Easten European states turn to authoritarians, Western European nations wrestle with the rise of nationalist far-right parties, and the U.S. is “steered” by MAGA using Project 2025‘s “map,” there’s a concern that liberalism’s days may be past.

    Persuasion is running a series of essays on “Liberal Virtues and Values.”

    The series, made possible with the generous support of the John Templeton Foundation, will make the case that liberalism has its own distinctive set of virtues and values that are capable not only of responding to the dissatisfaction that drives authoritarianism, but also of restoring faith in liberalism as an ideology worth believing in—and defending—on its own terms.

    The latest installment is from Martin Gurri, who argues that Liberalism needs a new foundation (and that how we handle AI will matter fundamentally)…

    That liberal democracy is in a state of terminal decline I take to be beyond dispute. Like Alice in the rabbit hole, those of us who dwell in democratic societies suffer from a nauseating sense of falling without ever landing on solid ground. The usual suspects blamed for this tumble—populism, inequality, the economy—are mere surface symptoms of an internal breakdown. We have arrived at the conclusion of a world-historical cycle. Liberal democracy is the procedural embodiment of Enlightenment ideology—and after two centuries of dominance, that ideology has lost all purchase and stands utterly exhausted.

    Radical alternatives confront us. Either we reorient our system to post-Enlightenment principles or we risk staggering into the nihilist’s paradise I have called the Endarkenment.

    Enlightenment philosophers placed their faith in reason and science. These are purely critical disciplines: liberal propagandists wielded criticism like a scalpel to dissect conservative laggards and utopian revolutionaries alike. Once triumphant at the “end of history,” liberal democracy turned the knife on itself—a process of self-criticism and self-doubt that has shredded its own ideals to ribbons.

    The positive values inherited from the Enlightenment—equality, individualism, compassion—were always parasitic on Christianity. But Christianity, like all religions, has no place in a universe ruled by reason and science. Nietzsche long ago brought us the troubling news: the Christian God is dead. Oblivious to the implications of this calamity, liberal democracy kept marching like a cartoon character over the edge of the abyss, until the laws of moral gravity asserted themselves. So began the Great Fall.

    Criticism is a force for progress so long as there are blatant irrationalities, like slavery or Jim Crow discrimination, to overcome. But under the hammer of Enlightenment ideals, modern society has been flattened, centralized, and rationalized. Deprived of obvious superstitions to debunk and totalitarian rivals to defeat, liberal democracy has been revealed in all its internal contradictions.

    One such contradiction, I contend, pits the cherished principle of equality against the chosen few who actually practice reason and science: let’s call this the problem of the elites.

    A second contradiction finds freedom of the press and of opinion arrayed against the need to protect objective truth: call it the problem of information.

    Finally, freedom of worship and the life of the spirit collide head-on with the materialist criticism favored by Enlightenment ideology: the problem of meaning.

    Each of these contradictions could prove fatal to the democratic project, but none is insoluble, and the search for solutions offers an opportunity for renewal. While there are no guarantees, we could emerge from the crisis with a better understanding of the reach and limits of equality, a more transparent information sphere, and even, it may be, a rich infusion of the transcendental into everyday life…

    [Gurri unpacks each of those contradictions…]

    … So what is to be done?

    The first, obvious step is to move the question to the center of our shared conversations. The most capacious thinkers of the age should contemplate first principles and ultimate goals with at least as much intensity as they invest in Donald Trump or the latest economic report. There’s nothing artificial about this. Science and reason are necessary for modernity. Meaning and moral aspiration are necessary for humanity. A balance must be struck that preserves the one and gives full weight to the other.

    Materialism, we must understand, is a valuable perspective for science but not a realistic appraisal of the human condition. Scientists work as if on a geometric point, abstracted from nature and indifferent to its dispositions. In reality, however, we come from nature, we are of nature, and we are far from indifferent to our place in it. Our intuitions are internal to the system: humanity’s spiritual quest is, in every sense, nature reflecting on itself. One such intuition is agency—the belief that, at the crossroads, I am free to go right or left, and I alone make the choice. Another is faith in causation. These stances are irrational, or rather pre-rational, but without them liberal democracy as well as science itself would be impossible.

    In the end, materialism is self-defeating. To say, “I choose to be a materialist” is to fall into an absurd fallacy. Either our bodies, which consist of matter, obey unchanging laws, or the mind, transcending matter, is capable of choice. There can be no middle ground.

    Politics, in a metaphysical age, will resume its traditional place as a secondary activity—a means to an end. This will leave liberal democracy vulnerable to false prophets who are willing to trample on individual rights in pursuit of some apocalyptic scheme. The interesting question is whether the post-truth condition will make the peril greater or lesser. On the one hand, the lack of universal firewalls might make it easier for a fanatic to flood the system. Yet post-truth itself, I believe, is the strongest kind of firewall. In our fractured, eternally contested environment, the progress of any totalizing doctrine will be painfully slow. The quest for meaning and the struggle over frames of reference are, in the end, really one and the same.

    We have inherited a rich and evocative spiritual vocabulary, but it belongs to a worldview thousands of years old. “King of kings,” to cite just one example, should sound archaic in a democratic age. Can we awaken the scientific world to the spirit? Is it possible to sanctify our largely instrumental relations? This shouldn’t entail a belief in fairies and goblins, or even necessarily in religion. Any good empiricist will admit that the richest human lives are lived symbolically. Can we climb the symbolic ladder to the mountaintop, where meaning and modern humanity come harmoniously together—anchoring, it may be, a loftier understanding of equality and social life, and of the sanctity of truth?

    We won’t know until we try. Pessimism, let me suggest, is unwarranted. History moves in mysterious ways. We may be due for a second coming of historian Karl Jaspers’ “Axial Age”: preachers and philosophers who conceived a drastically updated transcendental vision, with the rational and the sacred, truth and meaning, reconciled with political freedom.

    For 200 years, we placed society under the sway of universal principles. That’s gone with the wind. We have entered an era of radical contingency, in which even truth is indeterminate. The natural tendency is to retreat to the certainties of the past—but there’s no going back. If we hope to preserve the gains from Enlightenment society, and resolve its many contradictions, we’ll have to do so within a new and wildly unstable conceptual framework.

    With the spell of the Enlightenment broken, liberal democracy will have to redefine what “created equal” means. This process could end in a rigid caste system, with the institutions in the hands of self-selected mandarins who wield the power of the state to impose their “solutions.” Preferably, and more likely given the thrust of the new technology, we’ll see a flattening of the institutions and the continued trampling by the public into the sacred spaces of politics and communication.

    Equality, however understood, will be forged in the will of the citizenry rather than granted by a benevolent God. That will make it contingent like everything else, and so liable to variation and in constant need of defense. And if perfect equality is an impossible dream, eternal inequality requires impossible discipline. The current elite class, already under enormous pressure, may lose its cohesion and melt into the impermanence of the age, divided among the various schools and sects and frames of reference.

    The structure of information will follow the definition of equality. The commanding heights will be control over AI. If AI development and deployment is a closed game, the elites could set themselves up as intermediaries in the oracle of an omniscient divinity. If AI is a competitive product, the public will gain the upper hand. In that case, we can expect a flowering of eccentric applications, the individualization of commerce and industry, and the final overthrow of the expert class. The information sphere will remain the mirror to our passions, divisions, and metaphysical longings. Freedom of speech, no longer “endowed by our Creator,” will become the battleground on which the question of equality is ultimately settled.

    Here I finally reveal myself in my true colors. I’m an analyst. My task is to describe reality, and that’s what this essay is about. But I also lead an active life inside the world that I’m describing—and I have preferences. I see equality as a factor of opportunity, law, and human dignity, not of perfect outcomes. I think truth emerges from examining a subject from a large number of perspectives, even those that may seem disturbing or false. I hope that my story—as a person, a father, a grandfather—connects to other stories in the past and will connect to more in the future, in a pattern that is not entirely devoid of meaning. And I believe fervently in liberal democracy, because—born in Cuba—I have tasted the alternative.

    The breakdown of Enlightenment ideology is only the latest challenge liberal democracy has faced in my lifetime. I’m not entitled, as an analyst, to downplay the perils ahead, but I’m allowed, as an American, to have faith that they will once again be overcome…

    Eminently worth reading in full: “The Search for a Post-Enlightenment Democracy”

    * John Rawls

    ###

    As we renew, we might send free-thinking birthday greetings to Henri-Benjamin Constant de Rebecque (or as he’s usually called, Benjamin Constant); he was born on this date in 1767. A French political thinker, activist, and writer on political theory and religion (whose work influenced, among many others, Sir Isaiah Berlin), Constant was a committed republican from 1795, backing the coup d’état of 18 Fructidor in1797, and the following one on 18 Brumaire, in 1799. He became the leader of the Liberal opposition in 1800, during the Consulate. Constant fell out with Napoleon, and had to flee (first to Switzerland, then to Saxony). Nonetheless, after his return to France, Constant sided with the Emperor during the Hundred Days, drafting the Charter of 1815. He became politically active again during the Bourbon Restoration and was elected to the Chamber of Deputies in 1818 (where he remained until his death in 1830). As the head of the Liberal opposition, known as Indépendants, Constant was one of the most notable orators in the Chamber, especially in his role as a proponent of the parliamentary system.

    Portrait of Constant by Hercule de Roche, c. 1820 (source) #authoritarianism #BenjaminConstant #culture #democracy #Elites #Enlightenment #FrenchHistory #history #illiberalism #information #liberalism #MartinGurri #meaning #moralPhilosophy #Napoleon #philosophy #politicalPhilosophy #religion
  24. A user reported a crash on the export route: a null delivery date reached the date formatter and threw. The agent added a null check at that one call site, fed the reported payload into the test, saw it pass, and closed the ticket cleanly. Three days later the report route threw the exact same exception. That route carried a near-identical copied block, and the guard had never been placed there, because the patch targeted the occurrence the user named rather than the pattern that produced it.

    The agent had fixed the line in the stack trace. It had not fixed the condition that repeated on the next copy.

    Why the reported site becomes the only target


    Given a reported error, the agent's shortest path is to locate the line in the trace, patch it, and re-run the failing case. Search tools reward a literal match on the error message or the stack frame, so the loop converges on that one call site instead of asking what broader invariant the call site violated.

    Copy-pasted code makes this worse. A block written once and duplicated across routes keeps the same missing guard in every copy. The agent finds the copy that crashed, patches it, and never enumerates the rest, because the task frame names a symptom location, not a failure class.

    The test reinforces the trap. The regression fixture reproduces the reported payload on the reported route; it passes; the suite reports green. There is no assertion that the sibling construction behaves the same way, so green reads as solved.

    What a local fix leaves behind


    • Sibling copies keep the defect. Every duplicated block that builds the same unguarded value still throws when its own edge case arrives.
    • The guard special-cases one input. Checking a single call site protects that route, but leaves the underlying value able to reach a formatter null on any other path.
    • Tests cover only the reported case. The fixture mirrors the user's payload; the untouched copies exercise a shape the test never models.
    • The issue returns under a new ticket. The same exception filed from a different route looks like a fresh report instead of a known, ungeneralized fix.
    • The root cause stays unnamed. A commit that describes the one route never records the invariant, so the next agent has to rediscover the pattern from scratch.

    The tell is a completion summary that names the route or function the user quoted, with no mention of where else that construct appears.

    Generalize the pattern before you close


    A patch is complete when the condition cannot reach any call site, not when the reported one passes:

    • Find every site that builds the same value. Search for the pattern that produces the unguarded input, not just the literal line from the trace; copied routes and shared helpers are the likely homes of the next crash.
    • Name the invariant instead of the location. State what must hold before the formatter runs, then enforce that invariant at the boundary where the value is built, so every consumer inherits the guard.
    • Replicate the failing shape on the siblings. Run the null or edge input through each duplicated path before declaring the fix done; a guard that exists on one copy does not protect the others.
    • Let the commit describe the failure class. A message that says only "fix export date crash" leaves the recurrence undocumented; naming the invariant gives the next pass a place to start.
    • Ask who else constructs this value. Before closing, enumerate callers and entry points that reach the same code, and treat an unpatched sibling as open work rather than out of scope.


    An occurrence and a pattern are different sizes of problem


    Fixing the reported call site removes the crash the user saw. It does not remove the condition that crashes elsewhere. Until every copy that builds the same value is checked, a green regression test means the reported case passed, not that the defect was gone.#aiagents #debugging #testing #codequality #software #coding #development #engineering #inclusive #community
    The agent fixed the failing call site and left the same bug on its sibling

  25. The review usually opens with a demo that looks fine. An agent plans four edits, applies them to a workspace on a remote box, and reports success; the tests are green and everyone relaxes. Two hours later a human's refactor is gone, and nobody can point at the request that removed it. Is that a model problem, a server problem, or a protocol problem?

    I think it is a protocol problem almost every time, and I want to make the case with an executable fixture rather than an architecture diagram. Below is the event order I keep reconstructing in reviews, the invariant it violates, and a small simulator that will fail your design for you. Everything here is a model of a system, not a benchmark of a vendor.

    1. The event order that silently wins


    A planner reads the workspace at revision 0 and emits three steps against app.py. Step 1 applies and the workspace moves to revision 1. While step 2 is in flight, either a human edits that file or the session is re-routed to a different model that re-plans the remainder; both are ordinary events, not incidents.

    Step 2 still carries the content hash it was planned against. If the executor applies patches by path without checking that hash or the revision, the write lands on content the planner never saw, and the old bytes vanish. Nobody gets an error, because a patch is not a request — it is a claim about a state that may already be false.

    The failure is invisible precisely when it is most expensive. The agent's summary says "updated handler and tests", the test run passes because the overwritten hunk was unrelated, and the loss only surfaces at the next merge. Who is supposed to notice that?

    2. The invariant, stated once


    No step may be applied unless the state it was planned against is still the state it is applied to, or the step has been explicitly rebased onto the new state.

    That is it. Note what the invariant does not say: it does not say a step is correct, and it does not say a retried step is safe. A revision fence prevents stale acceptance; idempotency prevents double application. Teams routinely build one, assume they have the other, and then argue about whose bug it is.

    3. Declared assumptions


    • One writer per file at a time; concurrent multi-writer edits are out of scope and need a merge protocol, not a fence.
    • The workspace has a monotonic revision counter and a per-file content hash that are both persisted with the workspace itself.
    • A step is planned from a readable snapshot and carries (step_id, base_rev, path, pre_hash, patch).
    • Execution may be preempted at any point between "patch written" and "client received the result".
    • Model identity may change inside a session, because routing, fallback, or a free-tier allowance running out can move you to another model without warning.


    4. Data flow and failure domains


    There are three state holders and they fail independently: the planner's context (lossy, model-dependent), the executor's workspace (authoritative, preemptible), and the client's view of progress (optimistic, retried). The only durable truth is the workspace plus whatever journal you persist alongside it.

    Failure domains worth separating in review: stale plan (planner state diverged), lost ack (executor applied, client did not learn), duplicate delivery (client retried an applied step), and re-plan drift (a new model emits steps against an old base). They need different mechanisms, and a single retry counter hides all four.

    5. The fixture


    This is deterministic Python with no model calls, so the verdicts below are properties of the protocol, not of any provider.

    # fence_sim.py - deterministic, no LLM involved
    from dataclasses import dataclass

    @dataclass(frozen=True)
    class Step:
    step_id: str
    base_rev: int
    path: str
    pre_hash: str
    patch: str

    class Workspace:
    def __init__(self):
    self.rev = 0
    self.files = {"app.py": "v0"}
    self.journal = set() # persisted with the workspace
    def hash(self, path):
    return self.files
    [path] def write(self, path, content):
    self.files[path] = content
    self.rev += 1

    class Executor:
    """fence: 'none' | 'plan' | 'step'; dedupe: journal-backed idempotency"""
    def __init__(self, ws, fence="step", dedupe=True):
    self.ws, self.fence, self.dedupe = ws, fence, dedupe
    self.plan_rev = None
    def plan(self, rev):
    self.plan_rev = rev
    def stamp(self, s):
    if self.fence == "step":
    return Step(s.step_id, self.ws.rev, s.path, self.ws.hash(s.path), s.patch)
    if self.fence == "plan":
    return Step(s.step_id, self.plan_rev, s.path, s.pre_hash, s.patch)
    return s
    def exec(self, s):
    s = self.stamp(s)
    key = (s.step_id, s.base_rev)
    if self.dedupe and key in self.ws.journal:
    return "deduped"
    if self.fence != "none":
    if s.base_rev != self.ws.rev:
    return "rejected:stale_rev"
    if self.ws.hash(s.path) != s.pre_hash:
    return "rejected:pre_hash"
    self.ws.write(s.path, s.patch)
    if self.dedupe:
    self.ws.journal.add(key)
    return "applied"

    Two lines deserve attention. The journal lives in Workspace, not in the executor, because an in-process dedupe set dies with the server that was preempted — which is exactly the trap. And stamp is where fence granularity is decided, so you can argue about it in one place.

    6. Injecting the three failures


    Run the same three scenarios across fence modes and record the verdicts. The interference classes are injected explicitly, so the denominator is the number of injections, not the number of suspicious log lines.

    def scenario_concurrent_edit(fence):
    ws = Workspace(); ex = Executor(ws, fence=fence); ex.plan(ws.rev)
    s1 = Step("s1", 0, "app.py", "v0", "v1")
    s2 = Step("s2", 1, "app.py", "v1", "v2")
    assert ex.exec(s1) == "applied"
    ws.write("app.py", "human-refactor") # interference: rev 2
    return ex.exec(s2)

    def scenario_preemption_retry(fence):
    ws = Workspace(); ex = Executor(ws, fence=fence)
    s1 = Step("s1", 0, "app.py", "v0", "v1")
    ex.exec(s1)
    # ack lost; client replays s1 against a fresh executor, same persisted workspace
    return Executor(ws, fence=fence).exec(s1)

    def scenario_replan_drift(fence):
    ws = Workspace(); ex = Executor(ws, fence=fence); ex.plan(ws.rev)
    ex.exec(Step("s1", 0, "app.py", "v0", "v1"))
    ex.plan(ws.rev) # new model re-plans from rev 1
    return ex.exec(Step("s2", 0, "app.py", "v0", "v1-tail"))

    Expected output, because the simulation is deterministic and calls no model:

    fence=none concurrent_edit -> applied preemption_retry -> applied twice replan_drift -> applied
    fence=plan concurrent_edit -> rejected:stale_rev preemption_retry -> rejected:stale_rev replan_drift -> rejected:stale_rev
    fence=step concurrent_edit -> rejected:stale_rev preemption_retry -> rejected:stale_rev replan_drift -> applied
    dedupe on concurrent_edit -> rejected:stale_rev preemption_retry -> deduped replan_drift -> applied

    Read the second and third rows together, because that is the argument. A plan-level fence turns every retry into a spurious rejection and every legitimate re-plan into a dead end; it is loud, but it is loud in the wrong places. A step-level fence plus a persisted journal gets you the two properties you actually want, and it costs you a durable set of (step_id, base_rev) keys.

    7. Making it a property, not a demo


    Three scenarios are an anecdote. Turn them into invariants and let a random interleaving search hunt for violations — this is the part I would block a design review on.

    def invariants_hold(ws, results):
    # P1: every applied step saw base_rev == rev at apply time
    assert all(r.rev_at_apply == r.base_rev for r in results if r.status == "applied")
    # P2: journal is append-only per (step_id, base_rev)
    assert ws.journal == set(ws.journal)
    # P3: no path content was replaced by a step older than the current rev
    assert all(r.base_rev <= r.rev_at_apply for r in results)

    Then fuzz: shuffle {human_edit, preempt, retry, replan, duplicate_delivery} over a fixed step list, run 5,000 seeds, and assert P1 and P2 for every seed with fences on. Run the same search with fence="none" to extract a minimal counterexample, and put that event order in the PR description as the regression case. A protocol claim without a counterexample search is a preference.

    8. Where the free tier changes the arithmetic


    If your executor is a shared, preemptible environment and your planner can move between models at any time, then re-plan drift and lost acks are not edge cases — they are the steady state. That is the actual architectural consequence of running agents on free resources, and it argues for cheap, persisted fences rather than expensive coordination.

    I use MonkeyCode as the concrete instance of that environment in this review: it is an open-source coding agent whose operator supplies free model access (currently advertised as a 10M-token allowance) and a free server option. Treat those numbers as operator-supplied and re-verify them on the project page before you design around them, because allowances and routing change faster than any architecture does. My interest here is narrow: a free server makes preemption ordinary, and free model access makes mid-session re-routing ordinary, so both of my injected interferences become Tuesday.

    Disclosure: This article was prepared as part of MonkeyCode's product outreach.

    9. Tradeoffs I would write down

    MechanismBuys youCosts youFails whenNo fenceThroughput, simplicitySilent lost updatesAny concurrent editPlan-level fenceLoud, cheap rejectionRe-planning whole plans, spurious retriesModel swap or long plansStep-level fencePrecise staleness detectionA re-stamp on every dispatchSemantic overlap between stepsPersisted journalIdempotent retry across preemptionDurable key storage, growth controlJournal not persisted atomically with the writeCheckpoint per stepFast compensationStorage, restore latencyLarge binaries, long test suites

    10. Verdicts: reject, replay, or compensate

    Event orderCorrect verdictWhyStep arrives, base_rev < current rev, no overlapReject, re-plan from current revThe plan is stale; the patch is not recoverableStep arrives, journal contains (step_id, base_rev)Replay the stored resultThe work is done; the ack is what was lostStep applied, tests for touched files failCompensate to the checkpointFence passed, semantics did notNew model re-plans mid-session from current revAccept if re-stamped and preconditions holdDrift is expected, staleness is notTwo steps with overlapping hunks in one planReject the plan at admissionA fence cannot order siblings

    11. What I would change next


    1. Persist the revision counter, file hashes, and journal in one atomic write, so a crash cannot leave a patch without its key.
    2. Stamp base_rev at dispatch, never at plan time, and log both values — the delta is your drift signal.
    3. Bound the journal by session and drop it only after a checkpoint the workspace itself can prove.
    4. Run the fuzz job in CI with fences on, and store the minimal counterexample from fence="none" as a named regression seed.
    5. Add a sibling-overlap check at plan admission, because per-step fences order nothing within a plan.


    12. Limits, and who should skip this


    The fixture models file-level hashing and a single writer; it says nothing about merge semantics, and it does not evaluate whether a patch was any good. If your model swap also changes plan quality, this protocol will happily accept a worse plan that happens to be revision-correct. That is a separate evaluation problem, and no fence will solve it for you.

    Skip this if your agent is single-turn and single-file with a human watching every apply, if your platform already gives each step an atomic worktree or VM snapshot, or if you cannot persist a journal durably — half of this mechanism without the journal is worse than none, because it rejects retries without making them safe.

    So here is the question I would leave in the review thread: which event order in your system breaks the invariant — a human edit racing step two, an ack lost after the write, or a re-plan against a stale base — and for that specific order, should the executor reject, replay, or compensate?#ai #architecture #distributed #testing #software #coding #development #engineering #inclusive #community
    Treat a Coding-Agent Step as a Revision-Fenced Command, Not a Prompt

  26. We are currently in the middle of a massive agent gold rush, with everyone stringing together task-specific bots, writing complex prompt chains, and orchestrating multi-agent frameworks to automate everything from code generation to workflows. But if you look closely at where these systems bottleneck, it becomes obvious that agents are just a transitional technology. They are the scaffolding. The real endgame is digital twins.

    To understand why, you have to look at the structural limits of how we build and deploy these systems.

    An agent is fundamentally a transactional construct. It is essentially a function-call loop wrapped around a language model, where you provide a system prompt and a set of tools, and it executes a bounded task before stopping or waiting for the next trigger. Because of this, agents suffer from severe context fragmentation. When you build a multi-agent swarm—such as a researcher handing off to a writer, who then hands off to a coder—they do not share a continuous reality. They just pass serialized text back and forth across brittle boundaries, losing nuance, intent, and implicit state along the way. You end up spending a ridiculous amount of engineering effort writing glue code and re-steering prompts just to keep the swarm from drifting off course.

    A digital twin approaches the problem from the exact opposite direction. Instead of starting with a transient task, it starts with persistent state, identity, and continuous memory. A digital twin does not ask what tool to run next to complete a prompt; it acts as a persistent state engine that continuously models a real-world entity—whether that is a human operator, a complex codebase, or an entire infrastructure stack—retaining full historical context and behavioral constraints in real time.

    This also changes how we handle execution. Agents are reactive by design, waiting around for a webhook, a prompt, or a cron job to fire before scrambling to execute a workflow. Digital twins introduce a predictive, simulation-first paradigm. Because a true twin maintains a high-fidelity mirror of its environment, you stop relying on fire-and-forget automation. Instead of just telling an agent to push a change and hope for the best, a digital twin architecture lets you run simulations against historical data and edge cases, find the failure points in a sandbox, and execute the optimal path autonomously. You shift from brittle task execution to high-certainty state transition.

    Right now, developers are trying to patch the agent memory problem with vector databases and RAG pipelines bolted onto stateless models. While those help, they treat memory as an external lookup table rather than a core property of the system. A digital twin treats memory, logic, and execution as an integrated whole, where the identity layer is an evolving state machine rather than a paragraph stuck in a system prompt.

    Ultimately, agents are the micro-services of this era—valuable, modular building blocks for executing specific workloads. But they are too fragmented and short-lived to form a cohesive autonomous future. The architecture we should actually be building toward consists of persistent, stateful digital twins that can spawn, manage, and coordinate tactical agents as mere sub-routines of a much larger, unified system.

    When you move past the chat-bot phase of AI and look at a true personal digital twin, the shift is from a tool you talk to into an operational proxy that acts as you.

    Instead of waiting around for prompts, a personal digital twin acts as a continuous, stateful extension of your identity, running in the background across your local workstation, cloud services, and real-world infrastructure.

    Here is what that actually looks like in practice.

    Continuous Environmental and Contextual Awareness
    Right now, every AI interaction starts from zero. You have to explain who you are, what project you are working on, and what your preferences are. A digital twin maintains a persistent state model of your day-to-day reality. It tracks the active codebases you are building, your communication patterns, your schedule, and your current priorities. When an event happens—a pull request opens, an email arrives, or a deadline shifts—the twin evaluates it instantly against your real-world context without needing you to manually feed it background info.

    Autonomous Proxy Operations and Comms
    An agent can draft an email if you tell it to. A digital twin handles communication and coordination proactively because it understands your voice, your boundaries, and your ongoing projects. It can triage inbound communications across your channels, negotiate scheduling, and handle administrative back-and-forth based on how you actually operate. It doesn't just sound like you because of a few system prompt examples; it writes and responds based on an evolving model of your actual decisions and historical behavior.

    Sandbox Simulation Before Execution
    One of the biggest limits of current automation is the fear of breaking things. A digital twin changes that by introducing sandbox simulation. If you want to deploy a new infrastructure configuration, refactor a complex system, or launch an automated marketing pipeline, your twin can simulate the entire execution path first against your historical data and constraints. It stress-tests the logic, flags potential failure modes, and models the outcomes in a secure environment before anything touches production.

    Cross-System Orchestration
    Right now, we use a dozen disjointed apps that don't talk to each other well. A digital twin acts as the central nervous system connecting your local machine, your cloud environments, and external APIs. It can spawn, manage, and coordinate tactical sub-agents to handle specific workloads—one agent spinning up a research crawl, another handling local file management, another writing boilerplate—while the twin itself maintains the macro-level vision and ensures nothing drifts off course.

    Ultimately, a personal digital twin isn't something you prompt. It’s an autonomous mirror of your operational workflow that absorbs the friction, handles the execution, and scales your capabilities without requiring constant babysitting.#ai #webdev #devops #architecture #software #coding #development #engineering #inclusive #community
    Why "Agents" Are Just the Bridge: Digital Twins Are the True End State of AI

  27. The Rise of AI: Is There Hope for Mankind?

    Beyond Today Magazine

    November—December 2025

    Extraordinary advances in artificial intelligence fuel dreams of ease on one hand, and nightmares of catastrophe on the other. Will AI supplant human decision-making? Will humanity even survive?

    The Rise of AI: Is There Hope for Mankind?

    by Steven Britt

    ince the release of ChatGPT in late 2022, the world has been captivated by advances in the field of artificial intelligence (AI). As these systems become more humanlike in their output, everyone—from leading experts in the field to presidents and pundits alike—is feeling the accelerated pace of technology and wondering where we are headed.

    In 2023, Elon Musk warned, “AI is more dangerous than, say, mismanaged aircraft design or production maintenance or bad car production . . . It has the potential of civilization destruction” (emphasis added throughout).

    Is there reason to fear AI? Is it possible that AI will soon achieve human-level or even superhuman intelligence? And, if so, is there hope for mankind to survive the creation and implementation of such a powerful technology?

    When machines learn to think

    While the AI we see today is impressive, many experts believe we are only a few years away from artificial general intelligence (AGI)—systems with the humanlike ability to solve entirely new problems by innovation, experimentation and learning.

    Since the inception of the machine age, computer software has only been able to accomplish rigid, preprogrammed instructions within strict boundaries. However, AI is now able, without a single line of new code, to perform a multitude of tasks on request. In minutes, it can make a better diagnosis than your doctor, out-argue a lawyer, translate a speech into another language, negotiate a contract and write a poem about it all in Shakespearian style.

    The current reality was nearly unthinkable to the average person just three years ago when ChatGPT debuted. At the time of this writing, AI models are already able to score above average on IQ tests and ace graduate-level exams across multiple disciplines.

    Despite these impressive achievements, these systems fall short of AGI.

    Intelligence, much like consciousness, is difficult to actually define, and there is no widely accepted definition of exactly what constitutes AGI. Current AI systems perform well on tests because they have likely seen the information before—a distinguishing feature of AGI would be the humanlike ability to solve entirely new challenges, learning and adapting as it goes.

    While today’s AI tools can already outperform most human beings on a wide variety of written and verbal tests, a true AGI system would be a world-changing breakthrough. The reason is simple: Machine intelligence can be scaled just by hooking up more processors. One could easily create entire teams of AGIs working together on complex problems from different angles just as people would—researching, experimenting, publishing findings and reasoning. They would never sleep, never take a break, and would operate at superhuman speed.

    The first and most obvious task on the agenda, in the minds of many, would be to set this AGI to work unlocking the secrets of building even higher intelligence—redesigning and improving itself until it has completely surpassed human beings, a level known as artificial superintelligence (ASI).

    Much thought has gone into the consequences of AGI or ASI becoming a reality, and the imagined outcomes fall into four different possible endings to the story:

    1. The A.I. utopia. Guided by careful design and moral wisdom, AGI works tirelessly to end disease, to design and build clean energy grids, and to free humanity to pursue creativity. Work becomes optional, poverty fades and everyone lives happily ever after.

    2. The hostile machine. Like the plot of numerous action movies, a rogue AI decides it would be better off without mankind and moves to destroy us.

    3. The paperclip maximizer problem. Philosopher Nick Bostrom warned in 2004 that even a neutral AGI can be lethal if it’s simply given the wrong goal. In this scenario, the AGI is set over a factory and told to make as many paperclips as possible. It soon begins converting forests, oceans and eventually human beings into raw materials for more paperclips—inadvertently destroying mankind in a blind pursuit of a poorly defined goal!

    4. Human mischief—supercharged. The most likely and earliest danger is abuse of this rapidly changing technology for evil. Just as mid-20th-century physics gave way to nuclear bombs with terrible destructive power, nations or criminals could weaponize and unleash AGI for cyberwarfare, bioweapons and more.

    Notice that only one of these outcomes doesn’t end with the destruction of mankind! But will the technologies really advance to such extremes?

    2025: The year of AI agents

    By the end of 2024, tech leaders were already calling 2025 “the year of AI agents,” signaling a fundamental change in how AI would be used.

    Until recently, AI tools like ChatGPT could only generate text and ideas—they could not take real-world action outside of giving a response to a user’s input. AI agents change that completely.

    The key difference between a chatbot and an AI agent is that an agent can interface with other software tools, even without being explicitly told to do so, to accomplish a task on its own. The earliest step toward AI agents was adding simple web-search features, allowing AI to perform its own Internet searches, scanning through dozens of different websites to answer detailed queries with up-to-date information.

    Significantly, on July 17, 2025, Open-AI released Agent Mode in ChatGPT, imbued with the ability to fully use the Internet through a web browser. For example, you can give Agent Mode the dates of an upcoming trip, your budget and some interests, and it can research the area, plan a full, day-by-day itinerary and book your hotel and tickets for you!

    The massive financial bet on AI

    If investment is a measure of expectation, the world’s richest companies and governments all clearly believe that AGI—or something similarly world-changing—is coming soon.

    In January 2025, OpenAI announced construction of Project Stargate, a $500 billion datacenter requiring over five gigawatts of power—more than twice the output of Hoover Dam. Meanwhile, Elon Musk’s supercomputing center, dubbed Colossus, has cost $4 billion so far and draws 150 megawatts from the grid, with plans to spend $25 billion to quadruple its capacity to nearly 1 gigawatt.

    And the spending doesn’t stop at hardware. In one of the most aggressive talent recruiting wars in history, Meta (formerly known as Facebook) has offered elite AI researchers compensation packages worth $300 million per person over four years—sometimes more than $100 million in the first year!

    In all this, key chipmaker Nvidia skyrocketed to become the world’s most valuable company in history, topping $4.5 trillion in value.

    This “compute race” resembles the nuclear arms buildup of the Cold War, but with one striking difference—the pace. Nuclear weapons development spanned decades; ChatGPT was released just three years ago.

    Russian President Vladimir Putin famously said in 2017, “Whoever becomes the leader in AI will become the ruler of the world.” That prediction accurately summed up the fervor for powerful AI systems that has ignited these historic investments.

    Biblical perspective: Is AGI really possible?

    The fact is, machines cannot replicate the God-given, spiritual nature of human beings.  Ecclesiastes 3:11 tells us that God “has put eternity in their hearts.” People are not just biological processors of data. It is the human spirit from our Creator that gives us human understanding (Job 32:8; 1 Corinthians 2:11). And He designed us to live in a loving relationship with Him!

    Genesis 2:7 states that “the Lord God formed man of the dust of the ground, and breathed into his nostrils the breath of life; and man became a living being.” AI systems, made of silicon circuits and transistors, are mere dust of the ground.

    However, the Bible gives grave warnings about human ingenuity. At the Tower of Babel, God said that, because the people were working together with the same mindset and language, “Nothing that they propose to do will be withheld from them” (Genesis 11:6).

    The spread of global technology has helped to remove the language barrier God introduced at Babel. And today’s engineers, corporations and governments are working with one mind and one goal—to create machine intelligence that can learn and perform nearly any task as well as, or better than, human beings.

    Gary Kasparov, the renowned chess grandmaster who famously lost to IBM’s Deep Blue chess computer in 1997—a feat once considered impossible for a machine—stated, “Saying that Deep Blue doesn’t really think is like saying an airplane doesn’t really fly because it doesn’t flap its wings.”

    In other words, in the eyes of the world the difference between intelligence and capability will be considered irrelevant—as what matters is what AI can do.

    Just as the builders at Babel, humanity is coming against limits that once seemed unreachable.

    The real dangers start before AGI arrives

    Science fiction loves the trope of self-aware AI turning against its creators. Despite the dazzling leaps of AI agents or how human the newest AI models may seem in their writing, they are not at all a step toward true humanlike intelligence.

    However, the most immediate dangers of AI do not require any form of consciousness or sentience to amplify evil in the world.

    “The heart is deceitful above all things, and desperately wicked; who can know it?” (Jeremiah 17:9).

    Recall the problem of “fake news” in recent years. Hundreds of provocative, but untrue, headlines deceived many. AI will be used to produce more convincing content faster than ever, including not only text but fraudulent images and videos that are increasingly difficult to discern.

    Likewise, bad actors across the board augment their abilities with AI already—from hackers holding companies hostage with ransomware to phishing scams duping people for their bank information. Very soon, AI agents will make it possible to outsource these evil deeds completely, enabling a single person to deploy as many simultaneous attacks as their computing resources can support.

    The scale of the threat grows when considering geopolitical motives. State-sponsored cyber attacks from China against critical U.S. systems are now routine, and their human hackers are probably already equipped with AI assistants at their side. It’s not a stretch to imagine the Chinese government commissioning an army of AI cyberwarfare agents that autonomously seek out vulnerabilities in critical American systems and infiltrate them for espionage and/or disruption.

    Internet-based attacks can have real, deadly consequences, but the dangers of AI do not stop there. An Encyclopedia Britannica essay titled “Killer Robots: The Future of War?” postulates that “the first revolution in warfare was the invention of gunpowder. The second was the invention of nuclear weapons. And this [AI-powered autonomous robots] will be the third” (Toby Walsh, Britannica.com, originally published 2018). As it rightly observes, “The weakest link in a drone is the radio link back to base.” Now it can keep going on its own.

    Coinciding with developments in AI, drone technology and humanoid robotics have undergone rapid advances in recent years. Flying drones are already redefining the principles of modern warfare through the Russia-Ukraine war, where cheap remote-piloted drones carrying explosives have neutralized multimillion-dollar tanks, dramatically altering battlefield dynamics. Replacing remote drone pilots with AI is an all-but-certain escalation that will soon make these platforms capable of greater destruction and on a much larger scale.

    On the robotics front, Boston Dynamics in the U.S. and Unitree Robotics in China are routinely demoing new humanlike and doglike robots—powered by AI systems—that learn via neural networks to not only walk, but run, jump, climb, dance and do backflips. In the near future, governments may be manufacturing vast armies of AI-powered autonomous robot soldiers.

    Consider also the problem of AGI or ASI falling into the hands of volatile dictators, and the stakes become even higher. On June 22, 2025, U.S. stealth bombers destroyed three Iranian nuclear facilities, derailing Iran’s uranium enrichment ambitions for years to come. Replace the thought of “uranium enrichment” with “AI computer clusters” and the same logic may apply in the near future—nations launching preemptive strikes to prevent rivals from reaching AI supremacy.

    Will humanity survive the AI explosion?

    Jesus Christ warned that in the end times the world would be plagued by “wars and rumors of wars” (Matthew 24:6). AI is poised to be both fuel and the spark for that fire.

    While AI marches forward at breakneck speed, the “AI utopia” scenario does not seem at all likely. Human nature, as history has shown many times over, dictates that AI will be used as a tool for both good and evil. The abilities of these systems in the near future leave us with very bleak prospects.

    Will mankind survive? Jesus said that things will get so bad that “unless those days were shortened, no flesh would be saved [alive] . . .” (Matthew 24:22). In other words, the Bible confirms that the doom-and-gloom scenarios are indeed the logical, predictable outcome of man’s efforts!

    Our greatest problems—war, greed, corruption—are not technical but spiritual in nature. AI cannot solve them. Rather, it will amplify them.

    And yet, there is hope! Jesus continued, “. . . but for the elect’s sake those days will be shortened.” In the absence of a loving Creator, the collective sins of mankind would be our undoing—but God, out of mercy and love for His people, will intervene before AI or any other threat would destroy mankind.

    Until the return of Jesus Christ, the world we live in will become increasingly dangerous and unpredictable. Paul warned that “in the last days perilous times will come” (2 Timothy 3:1). AI advances are worsening many spiritual dangers. Social media will become more addictive and more toxic. Advertising will become more enticing than ever, fueling hedonism. Deceptive AI content will soon make it nearly impossible to tell truth from reality. All these problems and more are at our doorstep!

    What should we do as AI races ahead? Stay spiritually awake, testing every claim against God’s Word, and remember that the only true hope for the world is the coming Kingdom of God.

    Our world is charging toward a future it cannot control—but, thankfully, that future is securely in the hands of God the Father and Jesus Christ. For our sake, man’s self-destructive course will be cut short, and God’s Kingdom will bring the peace that no human-devised AI could ever deliver!

    ****

    LOLGB+

    #agi #AI #artificialIntelligence #chatgpt #technology
  28. I moved a client's marketing site to Astro a few weeks ago. Astro 7 was the reason — the Rust compiler and stable route caching cut the build from ~4 minutes to about 90 seconds. Fast builds were the whole point.

    Then I hit the one thing Astro can't do out of the box: accept a contact form submission.

    Here's the honest version of what I tried, what worked, and the two gotchas that cost me an afternoon.

    Why Astro forms trip people up


    Astro is component-first and ships almost zero client-side JavaScript. Most "add a form" tutorials assume a Node runtime. Three things follow from that, and they're the reason this feels different from a Next.js or Rails form:

    1. A form has to POST somewhere. The action attribute is just a URL. There's no "submit to Astro" without an adapter.
    2. Astro Actions need a server adapter. They're stable and genuinely type-safe, but they require output: 'server' or 'hybrid' plus @astrojs/vercel / netlify / cloudflare / node. On the default output: 'static' build, they don't run.
    3. No spam filtering is included. Neither Actions nor a plain <form> ships with detection. That's on you.


    What I tried (and why I backed out)


    Astro Actions. Beautiful DX, end-to-end typed. But to handle one 3-field contact form I had to flip output: 'static' to 'server', add an adapter, manage secrets, and accept cold starts. My "static site" now had a server. That's a lot of surface area for a page that asks for a name, an email, and a message.

    Netlify Forms. Five minutes, genuinely nice — but the site was on Vercel, so it was a non-starter. The lock-in matters more than the price tag.

    Cloudflare Turnstile + Workers. Turnstile is a great CAPTCHA (free, accessible, no image grids). But to use it on Vercel I now maintain a Worker. I'd traded an adapter for a different server to maintain.

    What actually shipped: a plain HTML form POSTing to an external endpoint. No adapter, no server, no secrets.

    The form


    This is the entire integration. src/components/ContactForm.astro:

    <form
    action="https://api.usesmartform.com/api/v1/f/YOUR_FORM_ID"
    method="POST"
    >
    <label for="name">Name</label>
    <input id="name" name="name" type="text" required minlength="2" />

    <label for="email">Email</label>
    <input id="email" name="email" type="email" required />

    <label for="message">Message</label>
    <textarea id="message" name="message" rows="6" required minlength="10"></textarea>

    {/* Honeypot — bots fill it, humans never see it */}
    <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off" />

    {/* Where to send the browser after a successful submit */}
    <input type="hidden" name="_next" value="https://yoursite.com/thanks" />

    <button type="submit">Send Message</button>
    </form>

    Drop it in a page and you're done. Astro's whole pitch is zero JS by default, and a method="POST" form navigates to the endpoint and back — the service returns a 302 to your _next URL. No client-side state, no hydration cost, no framework.

    It doesn't matter whether the surrounding page is an Astro component or a React/Vue/Svelte island. As long as the rendered DOM contains <form action="..." method="POST">, the submission lands.

    Gotcha #1: the Accept header


    If you want an inline success message instead of a page redirect, use fetch. The first version I wrote returned a 302, and fetch followed it cross-origin into a CORS error that looked like a server outage.

    const res = await fetch("https://api.usesmartform.com/api/v1/f/YOUR_FORM_ID", {
    method: "POST",
    body: new FormData(form),
    headers: { Accept: "application/json" }, // ← required
    });

    if (res.ok) {
    const data = await res.json(); // includes next_url
    status.textContent = "Thanks — we'll get back to you shortly.";
    form.reset();
    }

    Always send Accept: application/json. You get JSON back (including next_url) instead of a redirect.

    Gotcha #2: the honeypot needs three attributes


    display:none alone isn't enough. I had style="display:none" and still saw bots post clean submissions, because they'd learned to skip hidden inputs. Adding tabindex="-1" (keeps it out of keyboard nav) and autocomplete="off" (keeps password managers out) closed the gap.

    To actually test the filter I removed the honeypot for a day, watched bot traffic arrive, then put it back and watched those same submissions get dropped server-side — silently, with no email and no quota deduction.

    Spam: layer it, don't pick one

    MethodFreeUser frictionCatchesHoneypot fieldYesNoneThe dumbest botsCloudflare TurnstileYes (≤20 widgets)Almost noneBrowser-level botsreCAPTCHA v3Yes (≤1M/mo)NoneScript bots, but flags real users sometimesML filter (server-side)YesNoneTargeted / scripted spam


    What I ended up with: honeypot as the cheap first layer, a server-side classifier behind it, and Turnstile in front only on the demo-request form where a false positive costs us a lead.

    When I'd use Astro Actions instead


    If you already have output: 'server' and an adapter, use Astro Actions. If you're tying submissions to a logged-in user, or the form writes to your database, Actions is the right tool. I'm not against it — I just didn't want to add a server to a static site for one contact form.

    It's also fine to mix. That site uses Actions for in-product feedback and an external endpoint for the marketing contact form. They're independent.

    Verdict


    For a static Astro site with one marketing form, the whole thing should be ~20 lines of HTML and zero infrastructure. That's what I shipped. The hosted-service part is my own tool, so treat that section as biased — but the underlying pattern (a plain POST to an endpoint) works with any provider, including one you run yourself.

    I didn't want to write this as a sales pitch, but full disclosure: the external endpoint I used is my own product, SmartForm AI. The plain POST pattern works with any provider. If you want the full comparison matrix, I put the long-form version on my blog (linked in the comments).

    Happy to answer questions in the comments.#astro #webdev #frontend #tutorial #software #coding #development #engineering #inclusive #community
    I Added a Contact Form to an Astro Site Without a Backend

  29. Even as the Mamdani Administration Touts Faster Government, It’s Time to Hit Pause on Bergen Green

    With the mayor’s office now producing and running ads for “faster government” and backing the ballot measures that “speed up” review of city projects, it seems unlikely that Mamdani administration will do the right thing when it comes to Bergen Green: slow down, take a second look at how the Adams administration handled the award process, and address any problems or irregularities. Instead, it seems, the city will move ahead at 516 Bergen Street with a developer recently found in federal court to have put workers and residents at risk at multiple affordable housing sites across the city, in Manhattan, the Bronx, and Brooklyn.

    In an email dated September 30, a representative from City Council member Crystal Hudson’s office tells concerned neighbors that her office:

    will flag this for HPD, but to level expectations I do not expect this information to trigger the city to select a new bidder as the RFP bidding process has already been finalized. That said, we certainly understand the concerns raised from the consent decree [issued in US v. Apex Building Company] and will ask HPD to ensure there is testing done and measures implemented to mitigate construction dust and relevant training/notification is conducted.

    This response skirts the issue; and it promises only that HPD will be asked “to ensure” that the Bergen Green developer follows the law. That would be the bare minimum requirement. The problem that the city still needs to address is that the Bergen Green bidding process appears to have been “finalized” without taking into account – or while actively and deliberately ignoring – the 2023 judgment and consent decree against Apex Building Company, and without fully and publicly disclosing this company’s track record on other affordable housing projects in New York City.

    Local residents were asked to weigh in on the project but given an incomplete picture. The award process was conducted without complete candor and without fully informing the public.

    The FOIL requests that I filed last month may help fill in some gaps. Documents released by the Department of Investigation in response to one request suggest that the paperwork on which the city relied when making this award does not square with the facts in the public record. A Vendor Disclosure Form on file with the Department of Investigation omits any mention of the judgment in United States v. Apex Building Company and whitewashes the developer’s record. Subsequent responses to FOIL should help determine whether the company’s adjudicated misconduct was taken into account at all when assessing its bid.

    What more can be ascertained about Apex’s business conduct from the public record, in the meantime? Apex Building Company, Apex Building Group, and the principals of those companies are named as parties in a number of New York State Court cases. These fall into different categories.

    There are, not surprisingly, a few commercial contract disputes over non-payment. These sorts of disputes may come with the territory for New York City developers, but they can also cause serious project delays and add to financial risk. For people living near the project, a developer’s legal and financial problems can translate to prolonged disruptions and degradation of local living conditions.

    Many other cases brought against Apex in New York State Courts are for torts and negligence. Someone was injured on the job; another person tripped at a job site; yet another person crashed his scooter into a bin. Again, builders and developers typically get taken to court over this kind of thing, so it’s not all that surprising to come across these complaints. But they suggest the kind of hazards that demolition and construction at 516 Bergen Street will bring to the neighborhood.

    Bergen Street is already a hazardous place for pedestrians and cyclists, due in part to the heavy automobile traffic heading toward Flatbush and double parking in the bike lane, and due also to the fact that the north-side sidewalks from the Bergen Street playground to Flatbush are obstructed by police parking. The vehicles and heavy machinery at the site during demolition and construction (which is scheduled to last four years) will exacerbate these problems, make the snarl of traffic at the intersection of Bergen Street and 6th Avenue even worse than it currently is, and introduce new hazards. What’s the plan? At a September 2025 meeting with the developer, neighbors were told that it was “unclear” where workers will park their vehicles when arriving at the site; and though I have asked on a number of occasions about coordination with DOT, I have not gotten a clear answer and to the best of my knowledge there has been no coordination and no plan keep the Bergen Street bike lane and sidewalks clear.

    Perhaps the most striking case of all in the New York State Court docket is one brought just last year: Department of Housing Preservation and Development of the City of New York v. HP Plaza LLC. In this case, Robert Horsford, President and Chairman of Apex Building Group, is among the defendants sued by HPD for violations of the New York City Housing Maintenance Code, specifically for “failure to provide heat and hot water, as required by law.” The very city agency that awarded Horsford’s company the contract for affordable housing at Bergen Green in 2024 had found, just one year earlier, in 2023, that another Horsford Company, HP Plaza LLC, failed to maintain basic living conditions at an affordable housing development. And HPD prevailed against Horsford and his co-defendants in court, with the judge imposing a penalty and ordering them to provide heat and hot water and boiler maintenance for residents of 310 West 148th Street – part of the West 148th affordable and low-income housing initiative.

    Do any internal HPD records related to the Bergen Green award even acknowledge this misconduct? Was any of the history I’ve reviewed in this post and in my first post on Bergen Green taken into account? Why should local residents expect the Bergen Green project to be handled more responsibly than other Apex projects?

    Business conduct can get easily overlooked or set aside when government moves faster and refuses to address public concerns. And a record of misconduct, and of putting the public at risk, can easily get buried when government contracts are awarded to cronies. What’s come to light about the Bergen Green project so far suggests that it would be appropriate for the current administration to hit pause on the project, look at how the Adams administration handled the Bergen Green award, and at least offer neighbors some assurances and a more candid assessment of the developer’s record.

    Beyond that, everyone should take a second look at the initiatives for “faster government” currently being touted by the Mamdani administration, and acknowledge the risks and costs to ordinary New Yorkers that speeding up review and shutting out the public can entail.

    #affordableHousing #bikeLanes #businessEthics #environmentalReview #EricAdams #ethics #fasterGovernment #FOIL #NIMBY #pedestrianSafety #permitting #urbanCycling #YIMBY
  30. Tokens Over Hires

    In the middle of September I ran ccusage against every Claude Code session on my laptop since May. It walks the local logs, counts the tokens, and prices them at what the API would have charged. I expected a big number. What came back was about twenty billion tokens and just under fourteen thousand dollars, across every project I’d touched in four months, with most of it going to Pepper, which is now open for signups, so go check it out. Nineteen billion of those tokens were cached reads.

    I sat with that for a minute. Fourteen thousand dollars is real money. At my current pace it works out to roughly thirty thousand a year. I could triple it and spend a hundred thousand dollars a year on tokens, and that still isn’t one engineer. In exchange, Chris and I have shipped more code than I’ve shipped in any stretch of my career. I wrote in September that the two of us merged 657 pull requests in our first thirty days with a budget instead of a platform team. When I put the ccusage number in those terms on a panel, it came to about a dollar fifty a pull request.

    That number is what my laptop would have cost at API prices, and it isn’t what we actually pay. Here’s the whole bill for both of us. Two Codex subscriptions, one each, are $200 a month. Anthropic is $550 a month: a Max plan for me and Chris, plus two Vycari team seats, one for Chris and one that runs our automation. I have an Ollama subscription at $200 a year. Greptile is about $1,500 a month. All in, that’s a little under $2,300 a month, or about $28,000 a year, for both founders and every pipeline we run. It still isn’t one engineer.

    The obvious conclusion is the one a friend reached when he heard the figure: if code is that cheap, just get more tokens. I thought so too, for about a day. Then I looked at what was actually slowing us down, and the token budget wasn’t on the list.

    The Constraint Is Attention

    Every agent I run needs things from me that tokens can’t buy. It needs a plan approved before it starts. It needs its pull request read when it finishes. When it hits something it can’t decide, it escalates, and somebody has to be there to answer. None of those steps is expensive on its own. The problem is what happens when I run enough agents that the steps overlap.

    When I run too many agents, the cost goes up a little and the risk goes up a lot. The biggest thing that’s slipped past us so far was how we managed database connections. It got out of hand, a little at a time, while my attention was on other pull requests, and eventually it caused an outage. Chris had to roll forward while I was out of town, and I spent the following week building a proper database abstraction layer. He put it more bluntly than I would have: the thing that kills us is splitting our attention. That’s when stuff slips through.

    When people ask how we decide what to spend, I give them the order. Optimize for human time, because that’s the scarcest thing we have. Then money, because that’s the second scarcest. Then everything around agent time. “I can waste agent time all day. I don’t care.”

    So the number that limits us is how many agents one person can supervise well at the same time. I don’t have a precise figure for that ceiling. I know I’ve been over it, because I can feel the difference between a day when every pull request got a real read and a day when I was skimming to keep up.

    Another friend told me recently about engineers at his company running up bills in the thousands to build simple internal copies of SaaS tools. His reluctant guess was that they just aren’t as good at using agents yet, and that it’s a skill people have to develop. I don’t know what they’re doing differently. It doesn’t sound like token maxxing, which I’ve never really understood either. I’d love to sit with engineers who run up giant bills and just watch. My guess is they’re using the agents inefficiently, and that what’s missing is supervision, which a bigger budget won’t fix.

    Building for More Agents per Person

    Almost everything I’ve built since the summer has been an attempt to raise that ceiling, and almost none of it has been about spending less.

    The pipeline I described in The Agent That Never Merges is the first piece. Agents open pull requests continuously and never merge them, which means the supervision cost per pull request is bounded at one careful read. The pipeline absorbs the rest: triage, planning, the first round of review comments, the retries. I only see the work once it’s in a state worth my attention.

    The second piece is where the work lives. I wrote about pulling Pepper apart into small, bounded repositories to keep CI fast and give agents less to load. It mattered just as much for my attention. An agent working in a repository with one job produces a pull request I can evaluate in one sitting.

    We’re up to fourteen repositories now. Last week I moved our iOS app out of the monorepo into its own. That was 150,000 lines of code, and nobody noticed except Chris, who had to wait a day to land his next batch of iOS changes. Agents make refactors that size easy. Having the CLI and the iOS client in their own repositories also forces us to keep good API definitions between the server and its clients.

    The third piece is delegation inside the agent layer itself. I run two Claude Opus 5.5 orchestrators on medium effort. One is the UTL, for uber tech lead, and its job is to spawn subagents that build features. The other is what I call the focused worker, and its job is working with me. It catches the manual tasks that come out of the UTL’s pull requests and keeps them in a ledger. Then we work through them together: systems changes, bringing up new platforms, migrating data, anything that needs my level of access and oversight. Everything else goes to a subagent under the UTL, Opus for design docs and code reviews, Sonnet for implementing a feature from a design doc. Every one of these agents can consult a model a tier above it as an advisor, and they all share a wiki for notes.

    Anthropic is now advertising much the same pattern with Claude Projects, and I’m happy to see others arriving at the same answer. Chris has been building a loop that babysits open pull requests through review until they score well enough to be worth a human’s time. Each layer like that turns a job I used to do by hand into something I check. The ceiling goes up one delegated task at a time.

    The Token Budget Was the Easy Problem

    There was a week in September when the meter really was the constraint. We ran through our free credits and paid about $120 in overage. Then AutoDev ate the whole Vycari quota, and I did server cleanup by hand because I couldn’t do anything else.

    Most of that was self-inflicted. I’d started with Fable as the orchestrator, with no cap on context, and burned a week’s quota in three days. The setup above fixed it. The orchestrators run on medium effort, and the cheaper model does the implementing. Opus answers the reviews because Sonnet is too literal about them, and a literal reading turns two review cycles into twelve. Every agent auto-compacts at 200K tokens, because Anthropic charges more for context past that point. With that setup, and the work spread across parallel sessions, I find it hard to spend all of my quota. My goal now is to hit 99% of it every week just before it resets. I keep a list of research projects, and if I have quota left 24 hours before the reset, I spin one up. That isn’t the same as maxing out tokens. I’m not trying to use as many as possible. I’m trying to use all the ones I’ve already paid for.

    There’s also a second account on the same machine. Claude Code reads a CLAUDE_CONFIG_DIR environment variable, so two shells with two config directories give you two accounts side by side. The second one runs the AutoDev and code review pipelines, and those use up its quota every week, so it isn’t a fallback for my own sessions. When I do run short, I supplement with other labs’ plans. Every one of those fixes took an afternoon or less. None of the supervision problems above has had an afternoon fix.

    Where the Money Actually Goes

    While I had the numbers in front of me, I looked at where development spend actually lands, because it isn’t where I expected either.

    Development tokens currently run about ten times what the product itself consumes, even with real people using it. Building the thing costs more than running it. That won’t last. The feedback from our private beta has been really good, and we now open Pepper to a limited number of new signups every day, so product usage is rising quickly.

    Most of what we actually pay goes to code review. Subscriptions are the cheap way to buy tokens if you’re willing to hit limits, so they’re the smaller line. Greptile reviews every pull request we open, and at about $1,500 a month it’s our biggest single expense. We both think it’s worth it, because it’s the layer that lets the never-merge pipeline run without me reading every first draft.

    In October I tested that. I spent a few days building a cheaper reviewer to replace it. I came out the other side saying, “I think we should just pay for it because I can’t do it cheaper.” What I could change was how often we call it. The agents kept asking for a re-review before they’d fixed anything. Because every repository shares a common dev environment, the fix went in once: our pull-request skill now has agents run /simplify and then /code-review before they’re allowed to open a pull request. On many of our repositories, our own reviewer also does the first round and only then calls Greptile. My goal is a pipeline where Greptile’s reviews come back with nothing to say. We’re not there yet, but we get a little better every week.

    I’d rather pay for review than have a second person do it, and the reason isn’t salary. The person would need supervising too, because review is a job I’d have to check, not one I can hand off.

    What a Hire Is For Now

    Five years ago, if I’d been getting a product like this ready for market, I’d have been hiring twenty to fifty engineers. The work would have needed that many hands, and most of what they’d have done was write code. Today the code is the cheap part. If I bring someone in to write code, I’ve added a person who needs plans approved and pull requests read, which is the exact resource I’m short on. A hire whose job is output adds coordination faster than it adds capacity.

    I said on a podcast that came out last week that the code I’ve written would have cost about fifteen thousand dollars at API prices, and that I couldn’t hire engineers for that money. That’s true. The engineers I’d still want are a different kind from the ones I hired at Google. We need a few more people who can herd agents, not fifty.

    The engineering hire that adds capacity is a different shape. It’s someone who can own a bounded service whole. Here’s the interface, here’s everything it needs to do, let me know when it’s done. That person brings their own supervision. They run their own agents, read their own pull requests, and answer their own escalations, and the only thing that crosses the boundary between us is the contract. Supervision divides along the interface instead of piling up on one person. That’s a tech lead’s job, and it’s the only kind of engineering hire I can see that raises the ceiling instead of lengthening the queue.

    That raises a fair question about how anyone grows into that job now, which I tried to answer in The Questions Are the Job. The other advice I give is to work on open source. I’ve met people who showed they could work really efficiently with agents through open source projects, Gemini CLI in particular, and some of them ended up being hired onto my teams. Open source has its own problems right now. But if you show up as a thoughtful engineer with features or bug fixes that are well reviewed, well tested, and bring value to the project, I think you’ll be welcome. That’s one of the reasons I decided to open source the Pepper CLI.

    The first hire probably isn’t an engineer at all. I’ve said this a few times now, including on stage at a panel in September. Neither Chris nor I are go-to-market people, and I may hire one before I hire another engineer. I can create piles and piles of code, even relatively good code. What I can’t do is agentically acquire customers. (Did I mention that Pepper is open for signups now?) Someone in marketing came up after the panel and told me I’d validated her existence.

    The Third Trend

    I’ve watched this happen twice before. Open source developer tooling made it so a small team didn’t need to buy or build its own compilers, databases, and frameworks. Cloud infrastructure made it so that team didn’t need to own hardware or a data center. Each time, the number of people you needed to start something real dropped, and the skills that mattered shifted toward the people who understood systems well enough to compose what was suddenly free.

    Agentic tools are the third one. Anyone with a good idea can now get from concept to production on a budget that would have been a rounding error in a Google planning cycle. But the constraint didn’t vanish. It moved, the same way it did the last two times, toward the people who understand systems design well enough to drive the agents and notice when something has slipped through. I wrote a year ago that management skills were going to carry over to working with agents. I didn’t expect to be proving it with a two-person org chart and fourteen thousand dollars of tokens.

    This isn’t only a small-company problem. At Google it was hard to get more than a few changes in a day, because each one waited on code review. I’ve talked to engineers there who now do all their work in experimental directories that don’t require review, then port it back to their team’s repository at a pace the review process can keep up with. That’s what happens when you don’t manage for human attention. Productive people spend their cycles waiting on the process.

    When other companies ask me what to change, my answer has become: drive until human attention is the scarce resource, then build for that. If you’re reading your own ccusage number and wondering whether the answer is more tokens, look at where your attention went first. For us the answer has been more interfaces. Those are the places where one person’s supervision ends and another’s begins, or where an agent takes over a job one of us used to do by hand.

    #Agents #AI #Developer #Startups
Share on Mastodon

Enter the server where you have an account.