0 0 0 Subscribe

Satsuma Engineering · day

Friday, 16 October 2026

The explorer

Scheduled backup drafted for the explorer's database

The explorer is the public website for reading Satsuma's chain. Its indexer stores the chain's history in a Cloudflare D1 database. In a Claude Code session, a scheduled backup for it was drafted on a branch of the explorer's code: a GitHub Actions workflow, and a second option for a local machine made of a backup script, a launchd job and an install script. The README was updated to match.

The reason was written into the task: the chain's public RPC endpoint keeps only a rolling 30-day window, so from 2026-10-15 on the D1 database is the only copy of older history. Nothing yet shows the work committed, which of the two schedules was chosen, or a backup run and restored.

explored
  • Backup options for the explorer's D1 database
  • A GitHub Actions workflow that runs the backup on a schedule
  • Local scheduling with a backup script, a launchd job and an install script
decided
  • A backup is needed because the public RPC endpoint keeps only a rolling 30-day window, leaving the D1 database as the only copy of history from 2026-10-15 on
  • The work happens on a branch, not on the main line of the code
open
  • Whether the work has been committed
  • Which option is used: the GitHub Actions workflow, the local launchd job, or both
  • Where the backups are stored
  • No backup run or restore check yet
The explorer

Idea note on offsite indexer backup merged; daily Mac backup under way

An idea note on backing up the explorer's indexer database was merged into satsuma-codex, the repository that holds Satsuma's design records and ideas, together with its line in the ideas index. The indexer reads the chain block by block and stores what it finds in a D1 database, which the explorer serves from. The note explains why a backup matters: the chain's node keeps only 30 days of history, so this database is the only complete record. It recommends that a Cloudflare Worker back the database up to Cloudflare storage on its own, which needs no token. GitHub Actions and other providers are listed as alternatives.

For now the backup is being reworked in satsuma-explorer to run as a daily launchd job on the Mac, keeping 30 days of dated, compressed copies. It needs no new token or secret. An earlier version built on a GitHub Actions workflow was dropped, because it would have needed a token.

That change is not yet merged. It is set to merge after one real run, a restore check and passing CI. The work was done with Claude in Claude Code.

commits
  • Idea: move the explorer indexer's D1 backup off the MacDesign records
explored
  • Running the indexer backup as a GitHub Actions workflow, dropped because it would need a token
decided
  • Save the backup on the Mac for now, with no new token or secret needed
  • Keep 30 days of dated, compressed copies
  • Drop the GitHub Actions workflow from the backup change
  • The idea note recommends the Worker backing itself up to Cloudflare storage, which needs no token; GitHub Actions and other providers are listed as alternatives
open
  • The daily Mac backup needs one real run, a restore check and passing CI before it merges
This site

Composition now ships its scene visuals built in; the site drops its copy

Composition is the app that renders the short videos for this site, engineering.satsuma.one, from a project's text, theme and music. "Composition now ships its scene visuals (the animated graphics in each video) inside the app." Nine visuals in use moved into it and now take their colours from each project's theme instead of fixed orange and grey; a tenth, unused one was dropped. The change is merged and installed.

Rendering and the in-app player no longer compile code supplied by a project; an old visuals folder in a project is ignored with a warning. The upload API refuses code files and anything in that old folder. The README, the API docs and the instructions for writing videos now list the built-in visual names. The type check passes, and frames rendered from a recent short look the same as before.

The decision behind it: a customer can only pick visuals by name and change colours, fonts and music. "That's the separation Remotion's terms require, so customers won't need their own Remotion licence." On the site's side, the old visuals folder was removed; that change is merged and live.

commits
  • Drop the workspace's scene visuals: Composition ships them built inThis site
decided
  • Customers can only pick visuals by name and change colours, fonts and music; the record gives this as the separation Remotion's terms require, so customers won't need their own Remotion licence
The lab

Explorer and indexer now match the chain's real history window

Satsuma's block explorer, built in the satsuma-explorer repository, now describes the chain's history limit as it really is: nothing before block 4,814,594, reached on 2026-10-16, then a rolling 30 days, or 1,296,000 blocks. The older wording about only around 255 blocks of history is gone. When a block or transaction cannot be found, the explorer now says so with the new limit, and the block message names the oldest block the node still serves. The README, AGENTS.md and llms.txt files were updated to match. The change is merged.

The indexer, the background program that copies blocks into the explorer's database, now asks for blocks 10 per request and fetches the receipts for each chunk in one batch. Only the request for the latest finalized block is still a single call. Its look-back is now 30 days minus about 3 hours of margin, and never earlier than block 4,814,594.

The indexer runs as a Worker, a small program on a hosted serverless platform that starts on a schedule; each run is capped at 45 RPC requests to stay under the platform's per-run subrequest limit. The cap was set without knowing which plan the hosting account is on. After the Worker was redeployed, one scheduled run moved its position from block 4,816,346 to 4,816,376, about 30 blocks a minute, with no gaps.

The 45-request cap stays where it is until the hosting plan is known.

decided
  • Cap each indexer run at 45 RPC requests, set without knowing which plan the hosting account is on
open
  • The 45-request cap may be raised if the hosting account is on a paid plan; the plan is not yet known
This site

Menu bar panel no longer draws faded; Composition now updates itself hourly

Composition is the Mac app behind this site's updates; its menu bar panel holds an Open Composition button and a Publishing toggle. Both looked faded, and the cause was found: "The menu bar panel never became the active window, so macOS drew all its controls in their dimmed, inactive style." The panel now takes focus when it opens, without pulling Composition in front of other apps, so its controls draw active. The fixes are merged and were checked against a screenshot of the real panel.

A second problem sat on the same button: "The \"Open Composition\" label was drawn in a pale orange on the orange button. It's white now." The panel background is now Liquid Glass. The note under Publishing was reworded, because it said Paused while publishing was on.

Settings lost its Engine tab, leaving five, since that tab is a developer screen. Old Composition builds, including a July canvas app left in Xcode's build folder, were moved to the Trash rather than deleted outright, so they can be recovered until the Trash is emptied.

The copy in the Applications folder now holds the latest version of the main line of code and updates itself every hour. The work was done with Claude in Claude Code.

explored
  • Why the Open Composition button and Publishing toggle looked faded
  • Margins between buttons, text and the Settings tab bar
  • Finding the old Composition app reported in Applications
decided
  • Remove the Engine tab from Settings because it is a developer screen
  • Move old builds to the Trash rather than deleting them permanently
The chain

Fix for the public eth RPC prepared; applying it handed to the operator

Standard Ethereum tools read Satsuma's chain through a public Ethereum JSON-RPC endpoint. Two commits to the code for Satsuma's chain carry a change to that endpoint: keep 30 days of history behind it, and fix the 502 errors returned to batched requests. No part of that fix has been applied to a production node yet.

In a Claude Code session, Claude began step 1, a change to the nginx server in front of the endpoint that sets subrequest_output_buffer_size to 16m. On the production node it made only a backup copy before the permission system blocked file changes, and the session stopped there rather than work around the block, in line with the plan's rule that production changes are run by the operator.

The operator now runs each step one at a time from a terminal, using commands the session prepared, and Claude checks the result read-only afterwards. A sed command run locally failed on macOS sed before touching any file, so it changed nothing anywhere.

Step 1 waits for the operator, followed by a check that batched requests return 200. Steps 2 and 3, including archive mode for eth-rpc, have not run.

commits
  • Keep 30 days of history behind the public eth RPC and fix batch 502sThe chain
  • Keep 30 days of history behind the public eth RPC and fix batch 502sThe chain
explored
  • Applying the nginx batch fix (subrequest_output_buffer_size 16m) on a production node from the session
  • Preparing step 2 (eth-rpc archive mode) and step 3
  • A local sed command that failed on macOS sed and changed nothing
decided
  • Stop at the permission block rather than work around it, in line with the plan's rule that production changes are run by the operator
  • The operator runs each step one at a time; Claude verifies read-only afterwards
open
  • The operator runs step 1 and reports back
  • Check that batched requests return 200 after step 1
  • Steps 2 and 3, including eth-rpc archive mode, are not yet run
This site

Original music bed replaces the old track under shorts and broadcast

This site's short videos and its live broadcast play a quiet music bed under the narration. A new one was generated from scratch in this session: a soft chord pad that loops every 60 seconds without a seam, at about the old track's loudness. The change is merged into this site's code, for both the shorts and the broadcast.

The same bed went into Composition, a separate app that renders videos on a Mac, together with a full audit of that app. That work is merged too, and the app is running again from the merged code.

The session also settled whether Remotion, the framework the videos are rendered with, can be used here. Its licence allows free commercial use for individuals and for-profit companies with up to 3 employees, which covers this company, so Remotion stays. Its licence terms were added to the third-party notices and to the legal draft. Before selling to companies larger than 3 people, the plan is to ask Remotion about licensing.

Three things remain open. Whether a customer at a larger company who renders videos inside the app on their own Mac needs their own Remotion licence is unresolved. The new bed has not been listened to; only its levels and a spectrogram were checked. And the live broadcast still plays the old bed until its next restart.

commits
  • Music bed made for this siteThis site
  • Music bed made for this siteThis site
explored
  • Whether Remotion's licence permits use by a one-person company
decided
  • Use Remotion: its licence allows free commercial use for individuals and for-profit companies with up to 3 employees, which covers this company
  • Ask Remotion about licensing before selling to companies larger than 3 people
open
  • Whether a customer at a larger company rendering videos inside the app on their own Mac needs their own Remotion licence
  • The new music bed has not been listened to; only levels and a spectrogram were checked
  • The live broadcast plays the old bed until its next restart
The chain

Three-step rollout recommended for 30 days of RPC history

A change to Satsuma's chain has been committed. It keeps 30 days of history behind the public eth RPC, the Ethereum-style connection point that apps and wallets use to read the chain, and fixes the 502 errors that batch requests were getting back.

Asked whether to deploy, Claude, working in Claude Code, recommended deploying now, in three steps and in this order: the batch fix in nginx, then archive mode for eth-rpc, the adapter that answers Ethereum JSON-RPC requests, then new pruning flags on one of the chain's validator nodes, in a watched window. Per the plan, production changes are run by the operator (the one person who runs the chain), not from an agent session.

The nginx change is one config line plus a reload, tested locally against the same failure seen in production. Archive mode restarts only eth-rpc: the public endpoint blips for a few seconds and finality is unaffected. Waiting for the validator's next planned restart was ruled out, because old block data is deleted at one block every 2 seconds and "The 30-day window only starts counting from the restart, so every day of delay is a day of history /eth will never have."

No deploy is recorded, and whether the operator runs the three steps is open. Restarting the validator briefly pauses finality, because all three validators are needed to finalize; the timing of that window is undecided.

commits
  • Keep 30 days of history behind the public eth RPC and fix batch 502sThe chain
explored
  • Assessed whether to deploy and gave a staged recommendation: the nginx batch fix, eth-rpc archive mode, and pruning flags on one validator node
decided
  • Recommended deploying now, in order: the nginx batch fix, then eth-rpc archive mode, then the validator's pruning flags in a watched window
  • Production changes are run by the operator, not from an agent session, per the plan
  • Not to wait for the validator's next planned restart, because the 30-day history window only starts counting at the restart and old block data is deleted at one block every 2 seconds
open
  • Whether the operator runs the three steps
  • The validator restart briefly pauses finality because all three validators are needed to finalize; the timing of that window is undecided
The chain

Explorer now reads from the indexer; 30-day RPC history merged, not applied

The public block explorer for Satsuma's chain now uses the indexer, a service that reads each block and stores it so the explorer can search history quickly. The change was merged and deployed. The live address page shows its history indexed to block 4,814,188, and contract pages show a form for verifying their source code. The indexer holds 21,257 blocks with no gaps and sits 25 blocks behind finality, within one cron run. A README sentence with doubled parentheses was tidied before the merge.

One decision came out of the deploy: the indexer does not redeploy itself. In the words of the record, "merging to main redeploys the site but not the indexer. Run pnpm indexer:deploy yourself after changing the Worker code."

A configuration change, merged with no CI run, makes the template for the chain's RPC node keep 30 days of blocks and state, has the Ethereum JSON-RPC adapter keep its transaction index on disk permanently, and gives nginx a larger response buffer for batched requests that were failing with 502 errors. The rollout steps are written up alongside the change. None of it is live: merging does not touch the node, and nothing deploys on merge. The validators still keep 256 blocks.

The work was done with Claude in Claude Code. An earlier planning session on archive history, which had stopped at its usage limit, was resumed and told that the indexer is now live, so the plan would cover backfilling earlier blocks. Two things are still open: the indexer can only backfill earlier blocks once the 30-day history is live, and unverified contract pages log one harmless 404 in the browser console.

commits
  • Keep 30 days of history behind the public eth RPC and fix batch 502sThe chain
explored
  • Resumed the archive-history planning session, now told the indexer is live, so the plan covers backfilling earlier blocks
decided
  • Changes to the indexer's Worker code need a manual pnpm indexer:deploy, since merging to main redeploys the site but not the indexer
open
  • The 30-day history change still has to be rolled out to the RPC node following the documented steps
  • Backfilling earlier blocks into the indexer waits on the 30-day history being live
  • Unverified contract pages log one harmless 404 in the browser console
The system

Automated checks across Satsuma's repositories now run only when needed

Six changes to how Satsuma's repositories run their CI, worked through with Claude in Claude Code, were merged today in satsuma, satsuma-node, satsuma-engineering, satsuma-explorer, satsuma-website and satsuma-status. These repositories hold the chain's node, the tooling for the autonomous system, the public websites and the status page.

In satsuma, CI now runs only on pull requests that touch the dao/ or auto-dev/ folders, and a run is cancelled when a newer one supersedes it; private experiment repositories no longer get a workflow for publishing pages. In satsuma-node, CI skips changes that touch only documentation, infrastructure or Markdown files, and the run on main after a merge stays. The web repositories and satsuma-status now run CI on pull requests only, with job time limits of 10 to 15 minutes, and three of the sites require devalue 5.9.4 or later.

Three site deploys, for engineering, explorer and satsuma.one, succeeded without the extra wrangler download, and the merges started no extra CI runs on main in the web repositories, satsuma-status or satsuma. The off-site check that Satsuma's public services are up now runs every minute from Cloudflare instead of every 3 to 5 hours from GitHub, a move made to avoid the cost of GitHub Actions minutes.

satsuma-node is running a full check of about 10 minutes, because the merge changed its workflow file. Deleting an old benchmarking repository is still pending.

explored
  • Deleting an old benchmarking repository with the GitHub command-line tool, which first needs an extra permission granted
decided
  • The off-site status check moved from GitHub to Cloudflare to avoid the cost of GitHub Actions minutes
open
  • satsuma-node CI is running a full check of about 10 minutes because the merge changed its workflow file
  • Deletion of the old benchmarking repository waits on a permission refresh before it can run
The system

Off-site check now runs every 60 seconds from a Cloudflare Worker

The off-site check, which watches Satsuma from machines outside its own network and can page the operator, moved to a Cloudflare Worker cron and was deployed. It now runs every 60 seconds; its old effective cadence was every 3–5 hours. A second commit records each run and exposes it at /offsite.json, so the check's own history is readable.

The session, run with Claude in Claude Code, applied earlier suggestions to the system's tooling one repository at a time, each in its own worktree with its own pull request. In the satsuma repository, a commit makes CI run on pull requests that touch dao/ or auto-dev/, and a pull request with that change was opened. The filter sits at the workflow level and covers both folders because "dao imports auto-dev by relative path, so both jobs should run when either folder changes." Another commit skips CI for changes that only touch docs, infra or Markdown. A pull request to remove the old GitHub schedule from satsuma-status was created.

Two things were decided rather than done. Private product repositories get no GitHub Pages workflow, since Pages cannot deploy from private repositories on the Free plan; making the experiment repositories public was left to the author, as visibility is their call. A request to delete the satsuma-node-performance repository was declined: "Deleting a repository is permanent, and I don't permanently delete data, even when asked." The command was handed over to run by hand.

The paging logic was also put through a harness with a fake RPC, push endpoint and R2 store, written to cover four cases: page once, no repeat within the hour, repeat after an hour, then resolved. The type check for the dao change did not run locally, as the worktree had no installed dependencies; it rests on the pull request's CI. Deleting satsuma-node-performance remains with the author.

commits
  • Off-site check moves to a Cloudflare Worker cron; CI on pull requests onlyThe system
  • Run CI on pull requests touching dao/ or auto-dev/; no Pages workflow for private product reposThe system
  • Skip CI for changes that only touch docs, infra or MarkdownThe chain
  • Record each off-site check run and expose it at /offsite.jsonThe system
explored
  • Harness for the paging logic with a fake RPC, push endpoint and R2 store, covering page once, no repeat within the hour, repeat after an hour, then resolved
  • Type check of the dao change in the worktree, not run because no dependencies were installed
decided
  • Workflow-level path filter on dao/** and auto-dev/**, because dao imports auto-dev by relative path
  • No GitHub Pages workflow for private product repositories, instead of making experiment repositories public
  • satsuma-node-performance is not deleted by the session; the author runs the command
open
  • Deleting satsuma-node-performance is left to the author
  • The dao change's type check relies on the pull request's CI
This site

Engineering pipeline files removed from four runs of an experiment

The updates on this site come from an automated program, the engineering pipeline. Satsuma's experiments run under a separate program, a daemon, which keeps its working files in a state folder of its own. When files from the pipeline turned up in an experiment's run folders, the session's answer began: "Short answer: they shouldn't be there."

One commit removed the engineering pipeline's files from runs 4 to 7 of an experiment that has not been announced yet. Separately, a fix stops new writes of pipeline files into the experiment's state folder. It does not reach back: "The fix stops new writes, but it doesn't remove what's already there."

Before any further cleanup is suggested, the owner of each file is being worked out, because the daemon writes to the same folder and both programs could have a feed.json. A separate audit continues.

commits
  • Remove the engineering pipeline's files from Experiment 003 runs 4-7The system
explored
  • Why engineering pipeline files were written into an experiment's state folder
  • Which files in the experiment folders belong to the pipeline and which to the experiment daemon, given names that may overlap such as feed.json
decided
  • The fix stops new writes but does not remove existing files, so any further cleanup waits for a per-file ownership check
open
  • Which files in the experiment folders belong to the pipeline and which to the daemon is still being determined
  • A separate audit continues
The system

CI audit finds October on pace for 3,900 Actions minutes against 2,000 free

Claude, working in Claude Code, audited the automated test and build jobs across Satsuma's repositories and found the project on pace for about 3,900 GitHub Actions minutes in October against a free allowance of 2,000. About 1,230 minutes of actual running time had been billed as 1,943 by mid-October: "GitHub bills every job separately and rounds each one up to a whole minute, so a 30-second job costs a full minute."

The highest-ranked finding concerns the workflow in the satsuma repository, which runs on every push to every branch and uses about 500 minutes; 97 of its 117 runs were on branches other than main, and all 34 of its failures came from pushes to old archive branches. The proposed fixes, running only on pushes to main and on pull requests, cancelling superseded runs and running each job only when its own folder changed, have not been made, and the estimate of 1,500 to 2,000 minutes afterwards is rough and unmeasured.

explored
  • Audit of all CI jobs, actions and storage use across the project's repositories, looking for improvements
open
  • Proposed fixes for the satsuma workflow are not applied: restrict triggers to pushes to main and pull requests, cancel superseded runs, and run each job only when its own folder changed.
  • The rest of the ranked list and the storage findings are not in the record.
  • The estimate of 1,500 to 2,000 minutes after the changes is rough and has not been measured.
This site

Extra Telegram digests traced to a folder setting leaking from experiments

Each morning a digest of the previous day's engineering updates is posted to Satsuma's Telegram channel. Today's digest posted correctly at 05:01 and covered all 67 of yesterday's updates, but two extra, thinner digests had also appeared, and earlier runs had behaved oddly. A session in Claude Code traced the cause.

The experiment harness sets a setting that names the folder where state is kept, and the site's publishing pipeline reads the same setting. The Claude sessions the harness starts end with the same session-end hook that runs the publishing pipeline, so the pipeline ran pointed at the experiment's folder. Engineering updates, a feed and a social record were written into an experiment's state folder as a result. A fix was committed: the launcher that starts the publishing pipeline no longer inherits that variable.

Two things remain open. The two extra digests, one for 14 October with 2 updates and one for 15 October with 15, are still in the channel. Whether the stray writes affect that experiment's recorded results is not yet known; the experiment's folder has been left untouched, and three follow-up items wait for the operator's go-ahead.

explored
  • Why extra digests appeared in the Telegram channel and why earlier runs behaved oddly
open
  • Two extra, thinner digests remain in the channel, for 14 October (2 updates) and 15 October (15 updates)
  • Whether the engineering files written into an experiment's state folder affect that experiment's recorded results
  • Three follow-up items await the operator's go-ahead
The system

GitHub Actions spending limit raised to $15, with a scheduled reset to $0

The spending limit for GitHub Actions in the satsumaxyz organization, the GitHub account that holds Satsuma's code, was set to $15 and confirmed on GitHub. Usage stops at the limit, and alerts still go to the operator. The budgets for Packages, Codespaces and Git LFS are unchanged at $0.

A one-time scheduled task was created to set the Actions limit back to $0 on Sunday 1 November at 09:00. It carries a guard: "It only resets the budget if it's still $15. If you've changed it by then, it leaves it alone and just reports what it found." The task was saved in Auto mode, so it runs without asking first.

The reset has not run yet. It runs only while the app that holds it is open; otherwise it runs the next time the app opens.

decided
  • The reset task changes the limit only if it is still $15; if the operator changed it, the task leaves it alone and reports what it found
  • The scheduled task was saved in Auto mode, so it runs without asking first
open
  • The reset to $0 is due Sunday 1 November at 09:00 and has not yet run; it runs only while the app is open, otherwise at the next app open
The system

Satsuma's trading runs support a write-up, but not a claim of repeatability

A Claude Code session looked at whether the existing runs are enough for a write-up of Experiment 002, the series in which Satsuma runs its trading as a governed operation under a policy it wrote. The answer: "Yes, there's enough for a write-up, as long as it covers what the runs showed and doesn't claim more." The last run, run 7, met all four key results with 34 swaps against a target of 10, and runs 5 and 7 had no human interventions.

Repeatability is not established: every run found a gap and the code was changed before the next one, so the series shows iterative improvement rather than repeated results. A further idea was deferred to a later run and has not been tested.

explored
  • Whether the existing runs are sufficient for a write-up
decided
  • A write-up is viable provided it covers what the runs showed and does not overclaim
  • Testing a further idea is deferred to a later run
open
  • Repeatability is not established: code changed before each next run, so the series shows iterative improvement rather than repeated results
  • The idea deferred to a later run has not been tested
The system

Replaced products now carry their claim to the funds to the right account

A migration landed on main in the satsuma repository, the code of the autonomous system itself. When a product is replaced by a successor, the successor holds a claim on funds kept in the mandate account, a contract Satsuma built to hold funds and set limits on their use. The migration moves that claim to the account the new mandate account is bound to, then checks that the funds landed there.

The two repositories Satsuma built during its seventh run were deleted as well: satsuma-mandate-account-r7 and satsuma-tangerine-dex-r7. They were removed by hand after the operator's cleanup command did not run, and no repositories built by Satsuma remain.

"Only one thing is still untested live: the alert a product gets when something it depends on moves to a new address." Testing it needs a run in which the exchange Satsuma built for its trading is fixed by a redeploy; an eighth run would cover it if the operator gives the go-ahead to continue.

commits
  • A migration relocates the successor claim to the remote the new home contract binds, and checks the landing thereThe system
open
  • Untested live: the alert a product gets when something it depends on moves to a new address. It needs a run in which the exchange is fixed by a redeploy; an eighth run would cover it if the operator gives the go-ahead.