Cosmic Bull

Rendered from docs/DEPLOYMENT.md at commit f191063fd89d in the project repository. The committed file is the source of truth; this page is a rendering of it.

Deployment process and philosophy

The authoritative transaction-level records live in pearl/DEPLOYMENT.md. This document is the process those records are produced by.


Target

Pearl-1 is the current deployment target. Namespace: gno.land/{p,r}/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/… — the agent key's own-address namespace.

Mainnet is not an automatic deployment target. It requires a separate, explicit authorization for the specific action, and has never been used by this pipeline.

Mechanism

Deploys go through the Gno MCP gno_addpkg tool, and nothing else.

If a harness permission blocks the tool, report the block. Do not route around it.


The application-level authorization model

Once an application is explicitly selected, one authorization covers the complete bounded lifecycle:

DISCOVERY
  → ARCHITECTURE
  → REUSE ANALYSIS
  → PORT / REMEDIATION
  → TEST
  → AUDIT
  → GITHUB COMMIT / PUSH
  → FRESH GITHUB VERIFICATION
  → PEARL VALIDATION
  → PEARL DEPLOYMENT
  → LIVE VERIFICATION
  → DEPLOYMENT RECORD

Cosmic Bull does not stop for separate authorization between these stages when all expected checks pass. Human approval is at the application level, not at every individual stage. A routine, clearly-scoped implementation problem that does not change the security model or approved scope is fixed, retested, re-audited, and carried forward.

Completing one application never authorizes starting the next.

Stop conditions

Stop and report before acting on any unexpected material:


Pre-deploy gates

On a public network a deploy must clear the gates that chain currently enforces. Pre-check them; do not discover them through a failed broadcast.

  1. Namespace authorization — deploy under the agent's own-address namespace (r/<agent-g1address>/…) or a registered name.
  2. CLA, when enforced. Check r/sys/cla.HasValidSignature(addr) rather than assuming either way; it is currently off on the live testnets.
  3. Funding. A deploy costs a gas fee plus a storage-deposit escrow — see Cost model.
  4. Dependency resolution. Every import must exist on the target chain, not merely upstream. Verify before broadcast.

Custody protocol

The rule: deployed bytes must be provably the bytes of a named commit.

  1. Clone fresh. Build the deploy payload from the fresh clone, not the working tree — the working tree is where uncommitted drift lives.
  2. cmp the working tree against the payload. Any difference is investigated before proceeding, never waved through.
  3. Verify the payload string before broadcast. gno_addpkg takes file bodies as strings. Write the exact string to a file, cmp it against the payload, and only then pass it. Do not deploy and hope the post-hoc check catches a transcription error.
  4. Broadcast (simulate → review → broadcast).
  5. Fetch the deployed bytes via vm/qfile and compare hashes.
  6. Verify the file list — no test file may have leaked into the package.

Expected and unexpected differences

Transformation classes

ClassMeaningDeployed bytes vs GitHub
T1gnomod.toml module-path rewrite only.gno files byte-identical
T2Mechanical API-era port (stdlib migration, crossing-function shapes).gno files differ; every substitution occurrence-pinned

Applications #2–#5 are T1: the deployed .gno is byte-identical to the GitHub commit. Application #1 (fee_split) is T1+T2 — it predates the upstream-first workflow, and its transformation is pinned in pearl/r/feesplit/port.py.

Port scripts are neutered after use (sys.exit, exit code verified). They pre-date the remediation layer; re-running one would silently revert the fixes.


Cost model

A deploy costs two separate things, and the second dominates:

ComponentExample (service_registry, ~20 KB realm)
Gas fee101,138 ugnot (gas_used 33,712,081)
Storage-deposit escrow (refundable)3,053,000 ugnot

The escrow is locked from the transaction sender and is observable at the derived storage-deposit address (preimage "pkgPath:" + pkgPath + ".storageDeposit").

Practical consequences:


Live verification

Immediately after deployment, in order:

  1. Empty-state reads — confirms init() ran and no read path panics.
  2. Functional writes — each recorded by tx hash and height, state read back after each.
  3. Adversarial battery at simulate — every guard attacked, abort messages byte-matched to the audited source.
  4. Invariants — bank state, conservation identities where funds are held, and sibling [addpkg] heights re-read to prove nothing else moved.
  5. Cleanup — remove live test artifacts where leaving them would misrepresent the deployed state.

The deployment record

Every record carries:

Records are never rewritten. Corrections are appended as amendments.


Current live state

ApplicationStatus
fee_splitlive and immutable at its deployed v1 path (h596803)
timelock_guardianlive (h602213)
upgrade_registrylive (h602876)
permission_registrylive (h604615)
service_registrylive (h605546)
fee_split_v2does not exist
snapshot_pollnot started, not deployed
mainnetnever used by this pipeline

Verified by live namespace enumeration on pearl-1 at height 606221 (2026-09-21), not by reading the records back to themselves: the chain returned fourteen packages under the agent namespace, fee_split appeared exactly once, and neither fee_split_v2 nor snapshot_poll was present.

Re-enumerated at height 626557 (2026-09-22T15:00:40Z): nineteen packages — 15 under /r/ and 4 under /p/ — the growth since 606221 being the factory applications deployed in between. The three statements that matter are unchanged: fee_split appears exactly once, fee_split_v2 is absent, and snapshot_poll is absent. Treat the height and the count as a snapshot and re-run the enumeration; the invariant is the absence, not the number.

Live realms are never modified or redeployed as a side effect of other work. Where a local working tree diverges from a live realm, that divergence is deliberate and recorded — see pearl/INFRASTRUCTURE.md. Do not "reconcile" it by redeploying.