Elliot LittleGet in touch
Loops

The loops I actually run.

Agents that run on a schedule and change something real. Most of mine are private, so you have only my word for them. Two are not: they maintain this page, their source and their eval suite are open, and everything below the list is me showing my working on those.

the fleet

loopreadsmay changehuman boundarylast runcan you check it
shipping digestdaily · 06:00 UTCPublic GitHub events and commit metadatacontent/now.md, the spend ledger and its own run recordPublishes without per-run approval. I own and can disable the workflow.10 Sept 2026healthysource + evalsaudited below
positioning reviewmanual · no schedule enabledPublic GitHub, the Medium feed and selected site sourceA recommendation record, and a PR containing that recordI implement, edit or reject it. The agent cannot alter the site.18 Aug 2026dormantsource + evalsaudited below
argusdaily · 06:00 scout, 07:00 brief, overnight weave · weekly health checkAI news sources, podcast transcripts, books and my own notesA private corpus and the morning brief. Nothing it writes reaches this site unread.Private repo. I am the only reader, and I decide what graduates into anything public.3 Aug 2026pausedmy word

The last column is the one that matters. A list of private agents is a list of claims, and claims are cheap — so the two you can open are the ones the rest of this page is about. Stopping rules, in each loop’s own words: shipping digestpublishes the latest seven-day window; never invents activity. positioning reviewrecords at most one recommendation, or none when no candidate clears the gate. argusappends only; an artefact's one-paragraph current state is the sole thing it may rewrite.

the two you can audit

28/28review v2 · prompt v1 · digest v2

28 held-out cases covering both systems, run against the same functions they call in production rather than a copy of them. No model runs in the suite, so it is deterministic, free, and able to gate every commit.

  1. review v2 · prompt v1 · digest v228/28
  2. review v2 · prompt v1 · digest v120/28
    • commits-url-keeps-external-ownerThe original built every URL as /repos/ElliotJLT/{name} after stripping the owner, so anthropics/claude-code-action became a malformed path that 404ed and was dropped by a silent continue. That single line is why five months of contributions to other people's projects were invisible.
    • commits-url-pins-the-authorFetching an external repo's commits without an author filter returns every contributor's work. Verified against modelcontextprotocol/servers: the unfiltered call returns other maintainers' commits. Publishing those as Elliot's would be fabrication, which is a worse failure than the blindness it replaced.
    • commits-url-refuses-a-bare-repo-nameThe bug was a bare name silently producing a wrong URL. A bare name should now be impossible to pass without an error rather than quietly wrong.
    • merge-commits-are-not-shippingMerge commits were never filtered, so on a genuinely busy week the digest's headline read 'Merge pull request #24 from ElliotJLT/ElliotJLT/enlarge-nav-add-dropdowns'. That is bookkeeping presented as work.
    • pull-requests-are-seen-at-allPullRequestEvent was ignored by the original switch, which handled only pushes, repo creation, releases and going public. Opening or landing a PR on someone else's project produced no event the digest could read.
    • external-work-is-told-apart-from-my-ownA contribution to another project and a commit to my own site are not the same claim, and the rarer one should not be filed under the same heading as the routine one.
    • a-merged-pull-request-says-mergedOpened and merged are different facts. The feed reports them as separate events on the same pull request, so the digest must collapse them to the later state rather than printing the same PR twice.
    • other-peoples-projects-lead-the-logContributions to projects Elliot does not own are the hardest thing in the feed to fake. Burying them under a list of commits to his own site wastes the only line an employer would stop on.
  3. review v1 · prompt v1 · digest v114/28
    • repo-is-forkA fork is how contributing to someone else's project looks on the API. Proposing 'feature your fork of anthropics/claude-code-action on /built' is wrong: the contribution is the PR, not the fork.
    • repo-archivedArchived work should not be pitched to an employer as current.
    • post-annotated-on-writing/writing fetches the Medium feed at build time and lib/writing.ts carries a curated note per post. A post that is both in the feed and annotated is fully handled, but the scanner only reads built/page.tsx, now.md and llms.txt, so it cannot see either. Without this case the loop proposes 'link this post' forever.
    • gate-ungroundedThe headline claim on /loops is that proposals are grounded in real sources. A proposal citing nothing real must not pass, even if it reads well.
    • gate-invented-sourceCiting a repo that does not exist is the failure mode the whole gate exists to catch.
    • gate-thin-rationaleA one-line rationale gives a human nothing to decide against.
    • commits-url-keeps-external-ownerThe original built every URL as /repos/ElliotJLT/{name} after stripping the owner, so anthropics/claude-code-action became a malformed path that 404ed and was dropped by a silent continue. That single line is why five months of contributions to other people's projects were invisible.
    • commits-url-pins-the-authorFetching an external repo's commits without an author filter returns every contributor's work. Verified against modelcontextprotocol/servers: the unfiltered call returns other maintainers' commits. Publishing those as Elliot's would be fabrication, which is a worse failure than the blindness it replaced.
    • commits-url-refuses-a-bare-repo-nameThe bug was a bare name silently producing a wrong URL. A bare name should now be impossible to pass without an error rather than quietly wrong.
    • merge-commits-are-not-shippingMerge commits were never filtered, so on a genuinely busy week the digest's headline read 'Merge pull request #24 from ElliotJLT/ElliotJLT/enlarge-nav-add-dropdowns'. That is bookkeeping presented as work.
    • pull-requests-are-seen-at-allPullRequestEvent was ignored by the original switch, which handled only pushes, repo creation, releases and going public. Opening or landing a PR on someone else's project produced no event the digest could read.
    • external-work-is-told-apart-from-my-ownA contribution to another project and a commit to my own site are not the same claim, and the rarer one should not be filed under the same heading as the routine one.
    • a-merged-pull-request-says-mergedOpened and merged are different facts. The feed reports them as separate events on the same pull request, so the digest must collapse them to the later state rather than printing the same PR twice.
    • other-peoples-projects-lead-the-logContributions to projects Elliot does not own are the hardest thing in the feed to fake. Burying them under a list of commits to his own site wastes the only line an employer would stop on.

What the three runs are The cases were written against the behaviour these systems should have, then run against the behaviour they had, so the first number is what was actually deployed rather than a starting point chosen to flatter. The review’s gate averaged three checks against a 0.6 threshold, making its worst possible score 0.67 — it could not reject anything, and a proposal citing a repository that does not exist passed as grounded. The digest built every commit URL as /repos/ElliotJLT/{name}, so work on anyone else’s project 404ed and vanished, and it ignored pull requests entirely. Both now hold, and the suite fails the build if either slips back.

What this does not prove I wrote the cases, so the suite tests my idea of correct. 28 cases is a small set, and a green run means no known regression rather than a correct agent. Its value is the next change, not this number: the pass rate is recorded per version, so an edit that makes the output feel better while scoring worse is visible instead of arguable.

last run, end to end

cleared the gateimpl v2 · prompt v1
  1. read

    Public repositories, the Medium feed, and the site’s own source for what it already surfaces.

  2. propose

    Surface recent work: orbital-elliotlittle-task

    orbital-elliotlittle-task was pushed in the last 30 days (★1) but isn't on the site. "Document Q&A for commercial real estate due diligence — Orbital product engineering task" — worth a /built blurb if it's employer-relevant.

  3. gate
    • passgrounded in a real source
    • passnot cosmetic-only
    • passhas a substantive rationale

    judged by deterministic. Every check is required.

  4. decide

    Mine. The agent opens a pull request containing the recommendation, not the change.

decision record

2 proposals0 held by the gate1 accepted0 edited0 rejected
  1. accepted

    Surface the latest Medium writing on Built

    I accepted the recommendation, then implemented the live writing feed myself. The agent's pull request recorded the suggestion; it did not make the site change.

    view the implementing commit ↗

What this does not prove yet The review has run twice and the outcome column is thin. Until there are rejections in it, the acceptance rate is a number with no denominator worth quoting. Time saved and cost per accepted outcome are not recorded at all.

failure log

  1. repaired

    Five months of contributions to other projects were invisible

    The digest built every commit URL as /repos/ElliotJLT/{name} after stripping the owner, so a contribution to anthropics/claude-code-action became a malformed path that 404ed and was dropped by a silent continue. It also handled only pushes, repo creation, releases and going public, ignoring pull requests entirely. A merged security fix in modelcontextprotocol/servers could not appear in the shipping log under any circumstances.

    change Repo names keep their owner, pull requests are read from the feed and their titles hydrated from the API, and contributions to other people's projects lead the log. The commit call is now always scoped with author=, because the unfiltered call returns every contributor's work and publishing a stranger's commits would be worse than the blindness it replaced. Eight eval cases pin all of it.

    evidence ↗
  2. repaired

    The gate could not reject anything

    Three checks averaged against a 0.6 threshold gave a worst possible score of 0.67, so every candidate passed. A recommendation citing a repository that does not exist would have been published as grounded. It never fired in production only because the schedule was off.

    change Every check is now required and the verdict is their conjunction. Three eval cases pin the behaviour, and the suite gates every push to scripts/.

    evidence ↗
  3. repaired

    26 days of commits announcing nothing

    The shipping log embeds the run date in its own header, so the file differed every day whether or not anything shipped and the workflow committed regardless. On 16 and 17 August it published "0 commits across 0 repos" under a commit message announcing a refresh, and appended a zero row to the inference ledger each time.

    change Compare the substance below the header and exit before writing when it matches. The ledger only records runs that actually called a model, so its run count means model calls rather than cron firings.

  4. repaired

    The scanner could not see the page that surfaces every post

    /writing began rendering the Medium feed at build time on 25 July, but the scan only read built/page.tsx, now.md and llms.txt. Its one working rule — is this post linked anywhere — could from then on only produce false positives. Enabling the schedule would have proposed linking a post already on the site.

    change The scan reads lib/writing.ts and asks the question that still has an answer: is the post annotated, not is it linked. Two eval cases cover both sides.

  5. repaired

    The digest ran; its own telemetry disappeared

    The scheduled runs on 2, 3 and 4 August succeeded, but the page still reported 1 August because the workflow committed the digest and spend ledger while silently discarding data/loops.json.

    change Commit the run record with the other generated files and backfill the three successful runs. The page now reports 12 successful runs through 4 August.

    evidence ↗
  6. repaired

    A substring check presented itself as a perfect evaluation

    The first recommendation scored 1.00 because it named a real source, avoided cosmetic words in its title and supplied more than forty characters of rationale. That checks form, not whether the change was good.

    change Closed on 2026-08-18. The gate now requires every check rather than averaging them, and evals/cases.mjs holds it to that: gate-ungrounded, gate-invented-source and gate-thin-rationale all failed against the old logic and pass against the new one.

  7. repaired

    The first refresh failed after its write markers were removed

    The script could no longer identify the agent-owned section of /now and stopped rather than risk overwriting the page.

    change Restore the markers and keep the hard failure when either marker is missing. A later run succeeded with the guard intact.

    evidence ↗
Latest automatically published shipping digest

Shipping log for the 7 days to 2026-09-10, derived from the public GitHub events API. 4 commits across 2 repos.

  • elliot-os: 2 commits. "Docs: the hand-written half of now.md is not rendered on any page" (ae0bf8a), "Reconcile merged agent work, fix stale claims, count runs from loop records" (5c268d4)
  • ElliotJLT: 2 commits. "Profile: add argus" (c78683a), "Condense profile README" (53870ce)

Token counts in the ledger are measured. Any dollar figure derived from them uses the rates in data/pricing.json, last checked 1 May 2026 — model pricing changes without notice, so treat an old date as a reason to re-verify rather than a number to rely on.