0 0 0 Subscribe

Satsuma Engineering · day

Saturday, 17 October 2026

This site

Ownership article published, with a per-run breakdown of open defects

The article on Satsuma owning what it builds is published and live on engineering.satsuma.one. The page loads, it is listed first on the experiments page, and its card image is served. Two commits led up to it: one added glossary terms and four figures to the write-up, the other published it.

The article was shared in a 7-post thread on X and in a post to the Satsuma Telegram channel. Two choices were made along the way: the old approval-preview step was skipped and the posts went out directly, and the X thread was posted through a signed-in browser profile rather than with paid API credits.

After posting, the session broke down the 11 defects the article reports as unfixed. Across the runs, 20 defects were filed and 9 fixed: run 2 filed 3 and fixed 1, leaving 2 open; run 3 filed 1 and fixed none; runs 4 to 7 filed 12 and fixed 6; run 9 filed 3 and fixed 1, leaving 2 open. "The other 11 were still open when their runs ended. None of them was dismissed or closed by mistake." Separately, a bug in the loop that failed to find the migration function behind the proxy was fixed before run 11.

Two things stay open. The X thread's wording reads as if the 11 defects were ignored, since it does not say they were open at the end of their runs, and no correction is recorded. The X posting tool also lost its text box partway through; the thread is up, but how that was resolved is not in the record.

commits
  • Add glossary terms and four figures to the ownership write-upThis site
  • Publish the ownership write-upThis site
explored
  • Breaking down the 11 unfixed defects by run: 20 filed, 9 fixed, 11 open when their runs ended
decided
  • Skip the old approval-preview step and post directly
  • Post the X thread through the signed-in browser profile rather than paid API credits
open
  • The X thread's wording reads as if the 11 defects were ignored; no correction is recorded
  • The X posting tool lost its text box partway through; how that was resolved is not in the record
This site

A full article draft, laid out as a private page for reading on a phone

The full text of an unpublished article for this site, engineering.satsuma.one, now exists as a private page made for reading on a phone. It was built in a Claude Code session from the article's draft, at the operator's request.

The page holds the article word for word. Its two figures are stacked to fit a narrow screen, wide tables scroll sideways instead of being squeezed, and each glossary term links straight to its explanation. A list of sections sits at the top, and the page uses the site's own type and colours, with both light and dark modes.

The page is a private draft, not the article itself. The article is not yet published; it goes out once the billing for the automated build service it publishes through is unblocked. Changes the operator asks for after reading would be made to the draft and the page refreshed.

explored
  • Rendering a full article draft as a page laid out for a phone
open
  • Changes the operator asks for after reading would be made to the draft and the page refreshed
  • The article publishes once the billing for the automated build service is unblocked
Experiments

Builder's first interface check now accepts multi-interface files

Satsuma is an autonomous system that proposes software products, votes on them on its own chain, then has a language model, the builder, write and deploy the code. A fix to the first check that builder must pass, at milestone 0, is merged into the satsuma repository. The check looks for the file that declares a product's interface, the list of functions other contracts can call. It used to accept only a declaration whose name matched the proposal exactly. It now also accepts a file named for that interface that declares interfaces under other names: the file is published whole, marked as not an exact match, and logged. A file that declares no interface at all is still refused.

The cause showed up in a run of an unpublished experiment on local chains: "the proposer named the exchange's interface IUniswapV2; the builder wrote src/interfaces/IUniswapV2.sol as a family of interfaces (factory, pair, router…) with nothing literally named IUniswapV2; the milestone-0 gate accepted only an exact declaration and the retry told the builder nothing — five identical refusals across two exchange proposals, nothing deployed, no repos created." An earlier run had passed the same check only because its proposer happened to pick IUniswapV2Router02. Rather than let the stalled run continue, it was stopped and archived with its results and a list of interventions, and a new run was launching as the session closed, its chains up and its voting contracts deploying.

The builder's instructions now also say the file must declare interface <Name>, and explain how a protocol made of several interfaces does so. The work was done with Claude in Claude Code.

Still open: whether the upgrade path of a deployed product will be tested, and whether runs could use a development chain in place of a full Satsuma node, given that they make cross-chain transactions.

commits
  • Archive Experiment 003 run 10The system
  • Archive Experiment 003 run 10The system
explored
  • A run on local chains stalled at the builder's first check after five identical refusals across two exchange proposals
decided
  • Stop, fix and re-run rather than let the stalled run continue
  • Keep refusing files that declare no interface at all
open
  • A new run is in progress
  • Still open: whether the upgrade path of a deployed product will be tested, and whether runs could use a development chain in place of a full Satsuma node, given that they make cross-chain transactions.
The system

Upgrade-path test planned; local dev chain judged not worth it for runs

Satsuma can upgrade a product it already runs: a vote on its chain points a proxy contract at a new implementation, so the product keeps its address and funds while its code changes. Claude, working in Claude Code, planned how that upgrade path gets tested: a live test in the next run, plus a hardhat test of the logic that picks which contract counts as the new implementation.

The proposed hardhat test would pull that selection, about 25 lines, out into a pure function and check it against a real proxy, the old implementation, a V2 and a plain contract. That covers the choice, but not the vote itself: "The vote's upgradeToAndCall on the real chain is the one step nothing but a run can test."

The same session looked at whether runs could use anvil, a local development chain, instead of a Satsuma node. The recommendation was that it is possible in principle but not worth it, because the cross-chain layer the runs depend on is real: ISMP pallets with on-chain GRANDPA light clients, and a relayer. The proposed test is waiting for the operator's go-ahead.

explored
  • How to test the upgrade path: a live test in the next run plus a hardhat test of how the new implementation is selected
  • Whether runs could use an anvil/forge local chain instead of a Satsuma node, given cross-chain transactions
decided
  • Recommendation: replacing the Satsuma node with anvil is possible in principle but not worth it, because the cross-chain layer (ISMP pallets with on-chain GRANDPA light clients, relayer) is real
open
  • Whether the operator wants the proposed hardhat test of the implementation-selection logic
  • Whether the work is merged after the next run, or sooner if that run fails at the upgrade step
  • Whether an earlier price-guard issue recurs in the next run and gets fixed through the upgrade path
The system

Satsuma's repairs now choose between upgrade and migration by where the defect is

Satsuma's products are sets of smart contracts that the system builds and then operates, and some of them hold funds. When one has a defect, there are two ways to repair it: an upgrade, which swaps the code behind a proxy while the address and holdings stay put, or a migration, which moves to a new contract. Three fixes to how the system chooses and carries out these repairs were committed in one session.

The first fix is about how the system checks that a deployed contract offers the function a repair needs. The old check, deployedExposes, looked at the wrong place: "deployedExposes read the code at the claim's address — the proxy — which only carries upgradeToAndCall's selector." Its replacement, exposesAt, follows the ERC-1967 slot to the contract the proxy points to and checks that as well as the proxy. It was tested on hardhat against a real proxy.

The second fix changes how the assessor, the step that decides how a defect gets fixed, picks the path. A rule that a declared migration always wins is gone; when both paths are real, the assessor now decides per issue. The decision, as written in the session: "The real question is where the defect lies: in the proxied contract's code (upgrade — address, holdings and bindings stay) or in a contract the upgrade can't touch, like the RemoteAccount holding the position or an immutable router address (migration)."

The third fix makes the background process that runs deployments keep the same repository name across deploy attempts.

In the same session, a test run of an experiment that has not been announced yet was checked on its live chains before being stopped and archived, so the archive carries real counts: 26 proposals and 26 executed on chain, every key result met, and the books matching. The three code repositories created for the run were deleted. The record does not say whether the new code has run in a later test.

commits
  • Archive Experiment 003 run 9The system
  • Read a migration call through the proxy, let the assessor choose between upgrade and migration, pin the repo name across deploy attemptsThe system
explored
  • Tracing repeated run failures to their root causes instead of patching symptoms
decided
  • Choose between upgrade and migration by where the defect lies: in the proxied contract's code (upgrade) or in a contract the upgrade cannot touch, such as the account holding a position or an immutable router address (migration)
  • Check live chains before stopping them, so archives carry real counts
open
  • Whether the new code has been exercised in a later run is not stated in the record