尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證The spending agreement your house already has. Built for Total Recall (Tatum x Walrus).
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗The spending agreement your house already has.
unwritten-house.vercel.app · Track 03, Consumer Finance
Every household answers one question informally and never writes it down: who can spend what, alone, up to how much. Unwritten watches real decisions, derives the agreement, and tells you when the rule you think you have is not the rule you actually follow.
Built for Total Recall (Tatum × Walrus Foundation, 20 Oct – 10 Nov 2026) · Track 03, Consumer Finance.
unwritten-house.vercel.app opens on three doors:
Inside, the week control at the bottom replays the six weeks, and the role switcher shows what an owner, an approver and a spender each get.
The fastest way: /proof has a Run it live panel
that calls Tatum (checkpoint, house wallet) and Walrus Memory (the house's namespaces) from your
browser and shows the answer and its latency. Every blob id there links to its bytes on a public
aggregator and to its onchain record on Walruscan — size, storage epochs,
and the seal_encrypt_fence / certify_blob transactions. Transfers link to Suiscan.
pnpm verify
Asks the live relayer and Tatum directly and prints the relayer's health, the current Sui
checkpoint, and the memory count per namespace with a sample of each. The /proof page carries the
same data, the blob ids and explorer links. The product screens never show a hash — they live on
/proof, which the home page footer, the judge path and this README link to.
The Wilson house is seeded. A deterministic script runs the real engine over six weeks of household decisions and writes them to Walrus Mainnet. Nothing is faked downstream of that script, and every rule in the demo was derived by the same pure functions that run in production. We say this out loud because an undisclosed seed is the kind of thing a reader is right to distrust.
What is not seeded: the wallet. A daily GitHub Actions job signs small real transfers through Tatum's gateway ($1.00 of story money is 0.00003 SUI). About one in five is written without a decision on purpose, so Reality check always has something to find; the screen says so.
The Wilson house is not rendered from a local file. Every rule you see was recalled from Walrus
Mainnet and derived there by packages/policy — the belief ids on screen (vb-m1-groceries-v1,
drift-household-v1) are the ones the seeder wrote, and pnpm verify counts the same memories.
The sidebar says which it is. If the relayer is unreachable the app falls back to local fixtures and tells you so, because a screen that quietly shows local data while claiming to read Mainnet is exactly the kind of lie this project exists to avoid.
| Layer | What it does |
|---|---|
| Walrus Memory (Sui Mainnet) | every decision and every derived rule, append-only and versioned |
| Tatum Sui gateway (GraphQL) | reads the household wallet; catches spend with no approval. Not the Data API — it does not cover Sui |
packages/policy | the learning — seven dimensions, pure functions, no LLM |
The same diagrams render on /judge, from
apps/web/src/lib/diagrams.ts — this section is copied from that file, not redrawn. Every edge is
a call the code makes. The owner key never reaches the server; only the delegate does.
flowchart TB
subgraph BR["Browser"]
UI["Screens<br/>Agreement · Reality · Try · Proof"]
DER["policy.deriveAll<br/>re-run live on /proof"]
end
subgraph VC["Vercel · Next.js API routes"]
H["/api/house"]
C["/api/chain"]
S["/api/sandbox"]
K["/api/checkpoint"]
REC["reconcile<br/>day + recipient, never amount"]
end
subgraph WM["Walrus Memory"]
RL["MemWal relayer<br/>delegate key · Seal-encrypted"]
WB[("Walrus Mainnet<br/>append-only blobs")]
AG["Public aggregator"]
end
subgraph TT["Tatum"]
GW["sui-mainnet.gateway.tatum.io"]
end
SUI[("Sui Mainnet<br/>house wallet")]
GH["GitHub Actions · daily<br/>scripts/spend.mts"]
UI --> H
UI --> C
UI --> S
UI --> K
H -->|"recall · listNamespaces"| RL
S -->|"validate → budget → remember"| RL
C -->|"recall decisions"| RL
C -->|"transactions · sentAddress · address · balances"| GW
C --> REC
K -->|"checkpoint · sequenceNumber"| GW
RL --> WB
WB --> AG
UI -.->|"blob ids on /proof resolve here"| AG
GW --> SUI
GH -->|"executeTransaction"| GW
GH -->|"writeDecision"| RL
DER -.-> UI
Reality check — one request, both networks. An unmatched row exists in neither source alone.
sequenceDiagram
autonumber
participant B as Browser
participant A as Vercel /api/chain
participant T as Tatum gateway
participant S as Sui Mainnet
participant M as MemWal relayer
participant W as Walrus Mainnet
B->>A: open Reality check
A->>T: transactions · sentAddress · house wallet
T->>S: read
S-->>T: outgoing transfers
T-->>A: transfers · paginated, retried on 503
A->>T: address · balances
T-->>A: balance → low-balance nudge
A->>M: recall decisions
M->>W: fetch blobs
W-->>M: Seal-encrypted payloads
M-->>A: decisions, decrypted for our delegate
A->>A: reconcile · match by day + recipient
A-->>B: rows · approvalId null = spend nobody agreed to
Note over B,W: An unmatched row exists in neither source alone — that is the integration
The daily history — why the chain holds real days rather than one afternoon of transfers.
sequenceDiagram
autonumber
participant G as GitHub Actions · daily
participant T as Tatum gateway
participant S as Sui Mainnet
participant M as MemWal relayer
participant W as Walrus Mainnet
G->>T: has today already been sent? transactions · sentAddress
T-->>G: count of today's transfers
alt already sent
G->>G: exit — the chain is the idempotence guard
else not yet
G->>T: executeTransaction · house key
T->>S: transfer
S-->>T: digest
T-->>G: confirmed
opt the household agreed to it
G->>M: writeDecision · only after the transfer confirms
M->>W: append blob
end
Note over G,W: ~1 in 5 has no decision on purpose — Reality check is meant to find it
end
Everything runs on Mainnet, which turned out not to be a choice. A spike before the build
window found that sui-testnet and sui-devnet both return 404 on our Tatum key — only
sui-mainnet is reachable — and that the Walrus Memory credentials are mainnet-only, since
staging rejects an account that does not exist on that network.
So the two-network design we had planned was not available, and the result is simpler than what we set out to build. Development writes are kept away from the seeded house by namespace rather than by network.
/observer illustrates it.ratified with nothing behind it.
The reverse order is recoverable: retry the write, keyed by belief id.rhythm dimension exists at all./keys plays the
protocol's behaviour locally (the rotation counter moves, the next remember() fails) and says so
on the screen./digest builds no transaction
and writes nothing to Walrus — it changes local state and prints log lines marked SIMULATED. The
Move package that would hold the ratified agreement does not exist, and the ratifiedTx on a
seeded belief is a placeholder rather than a real digest. Every Walrus write the product makes
(the seed, the daily job, a visitor's sandbox) and every Tatum read is real; ratification is the
part that is not./proof checks that sentence by sentence.docs/specs/ one spec per feature, Given/When/Then — code is built from these
packages/policy the seven learning dimensions, pure functions, fully testable offline
packages/memory the only caller of the Walrus Memory SDK
packages/chain the only caller of Tatum
prototype/ the clickable field-discovery instrument the schema was derived from
PLAN.md anti-drift: artifacts, build order, and 25 invariants
Two wrapper packages exist so that one file answers "where is every Walrus write" and one answers "where is every Tatum read".
The first version of the main screen was generated on ai.tatum.io and is kept in its own repository — EdCryptoFi/unwritten-ai-builder — rather than squashed into the first commit here, so the lineage is verifiable instead of asserted.
What survived into this codebase: packages/chain is built on its server/tatum-client.mjs, whose
comments document four traps that each would have cost hours (a key works on api.tatum.io or
api.tatum.dev but never both, and the wrong host answers 401; a spread Headers silently drops the
key; read env per call; derive the gateway host from the API base). The semantic names in
globals.css (text-brand-primary, utility-brand-50, bg-primary-hover…) also come from the
generated tokens.
What did not: the palette. The generated screen used Tatum's brand colours; the visual system was later replaced by a claymorphism one, so the colours and shapes you see are not Tatum's. Nor did the single-file shape survive — the generated screen held state, fetching and rendering in one place, and the seven learning dimensions had to become pure functions before they could be tested without a browser.
MIT.