@bloxwap/agent-cli 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # @bloxwap/agent-cli
2
+
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Support user-owned EOA trading agents (`signerType: eoa` with a local `eoaKeyRef`)
8
+ alongside user-owned Privy apps. The default Bloxwap builder fee is now zero, with
9
+ optional non-zero overrides, and the default BLOXWAP referral is applied after
10
+ agent approval when the account has none. Testnet approval errors now keep the
11
+ action and upstream rejection, and preflight requires a positive test USDC balance.
12
+
13
+ ## 0.2.0
14
+
15
+ ### Minor Changes
16
+
17
+ - a04a6c7: Add managed Hyperliquid agents, Relay funding, JSON commands, a persistent runner,
18
+ risk checks, durable events/audit journals, and the packaged trading skill.
19
+
20
+ ### Patch Changes
21
+
22
+ - db928e2: Ship license, changelog and repository metadata with the CLI. Verify script-free
23
+ global npm installs and installed bunx execution on macOS/Linux and Node 22.12/24.
24
+
25
+ ## 0.1.0
26
+
27
+ Initial implementation of managed-agent trading, funding and persistent runner.
28
+ Use Changesets for subsequent versioning and release notes.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Bloxwap contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,82 @@
1
- # Temporary Holding Version
1
+ # agent-cli
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ An agent-native Hyperliquid trading CLI with JSON input/output, a persistent
4
+ signing runner, user-owned Privy or EOA agents, Relay funding, a packaged agent skill,
5
+ and a paper trading mode against real mainnet market data.
6
+
7
+ After the first public release, install with `npm i -g @bloxwap/agent-cli` or run
8
+ `bunx @bloxwap/agent-cli --help`. Use Node **22.12+** or Bun;
9
+ `bunx --bun @bloxwap/agent-cli --help` explicitly selects Bun.
10
+ The package has no install lifecycle scripts and supports `--ignore-scripts`.
11
+ Until publication, build a local tarball with `npm run build && npm run pack:cli`
12
+ from the repository root and install that tarball with `npm i -g PATH_TO_TARBALL`.
13
+
14
+ ## Paper trading
15
+
16
+ Simulate strategies against real mainnet Hyperliquid market data with no
17
+ signing and no funds: `paper reset --yes`, then trade with the global `--paper`
18
+ flag (or `config set mode paper` / `run --paper`). The simulator walks the live
19
+ book, charges Hyperliquid taker/maker plus the optional builder fee (zero by
20
+ default), accrues funding, approximates margin/liquidation, and keeps restartable state under
21
+ `~/.bloxwap/paper/`. `paper summary` reports PnL, fees, funding and trades.
22
+ Envelopes and events carry `mode`/`paper` labels; `config set mode live --yes`
23
+ is the explicit way back to live. See `docs/paper.md`.
24
+
25
+ ## Testnet quickstart
26
+
27
+ Use your own Privy app or a dedicated EOA agent. No wallet or credentials are
28
+ bundled. Set secrets locally outside the CLI/conversation, then configure only
29
+ their references:
30
+
31
+ ```sh
32
+ npm ci
33
+ npm run build
34
+ # Privy:
35
+ node packages/agent-cli/dist/cli.js config set signerType privy
36
+ node packages/agent-cli/dist/cli.js config set privyAppId YOUR_APP_ID
37
+ node packages/agent-cli/dist/cli.js config set privyAppSecretRef env:BLOXWAP_PRIVY_APP_SECRET
38
+ # Or a user-provided EOA agent (BLOXWAP_EOA_KEY is set locally):
39
+ node packages/agent-cli/dist/cli.js config set signerType eoa
40
+ node packages/agent-cli/dist/cli.js config set eoaKeyRef env:BLOXWAP_EOA_KEY
41
+
42
+ node packages/agent-cli/dist/cli.js init --network testnet --master-address 0xYOUR_MASTER_ADDRESS
43
+ # Sign the returned agent approval externally and resume init.
44
+ # Init applies the BLOXWAP referral if the account has none.
45
+ node packages/agent-cli/dist/cli.js status --network testnet
46
+ node packages/agent-cli/dist/cli.js run --network testnet --detach
47
+ ```
48
+
49
+ Testnet onboarding requires your selected signer, external master approvals and
50
+ testnet collateral. The EOA must be separate from the master wallet. Never put a
51
+ private key, seed, or app secret in CLI input. Replace all placeholders with your
52
+ own values. Read [custody limits](../../docs/custody.md) before funding.
53
+
54
+ ## Architecture and custody
55
+
56
+ ```mermaid
57
+ flowchart LR
58
+ Agent[Agent / CLI] -->|private JSON-RPC| Runner[Persistent runner]
59
+ Runner --> Signer[User-owned Privy or EOA agent]
60
+ Signer -->|EIP-712 signature| HL[Hyperliquid exchange]
61
+ Agent --> Relay[Relay funding quote]
62
+ Master[External master wallet] -->|one-time approvals| HL
63
+ Runner --> Journal[Events / audit / logs]
64
+ ```
65
+
66
+ Master custody stays external. The user owns the Privy app or local EOA agent key.
67
+ Hyperliquid agent permissions deny withdrawal. Local typed-data and risk checks
68
+ apply to both signer types; Privy policies add remote restrictions for Privy agents.
69
+
70
+ State: `~/.bloxwap`; config: `~/.bloxwap/config.json`; IPC:
71
+ `~/.bloxwap/run.sock`; env prefix: `BLOXWAP_`. All local state is private to the OS
72
+ user. The default Bloxwap builder address is
73
+ `0x71b09A08257078A4d642F7Dd7315e656c837329a`, with `f=0` (no added fee).
74
+ The default `BLOXWAP` referral is applied during approved onboarding when the
75
+ account has no referral. Optional non-zero builder fees remain configurable and
76
+ require master approval.
77
+
78
+ ## Development and docs
79
+
80
+ Use Node.js 24+ and run build, lint, typecheck and tests from the workspace root.
81
+ See the [repository README](../../README.md) and [docs app](../../apps/docs/README.md).
82
+ The packaged [SKILL.md](SKILL.md) documents the authorized agent workflow.
package/SKILL.md ADDED
@@ -0,0 +1,193 @@
1
+ ---
2
+ name: agent-cli
3
+ description: Operate the agent-cli Hyperliquid trading CLI, including managed-agent onboarding, paper trading against real market data, funding, orders, event monitoring, rotation, and normalized error recovery.
4
+ metadata:
5
+ version: "0.3.0"
6
+ ---
7
+
8
+ Use `agent-cli` for the user's authorized Hyperliquid account operations. Obtain
9
+ command schemas with `agent-cli schema COMMAND`; arguments can be flags or
10
+ `--json '{...}'`, or a JSON object on stdin. Ordinary commands print exactly one
11
+ JSON object: `{ok:true,data,mode,paper}` or
12
+ `{ok:false,code,message,retryable,details,mode,paper}`; `mode` is `"live"` or
13
+ `"paper"` and `paper` is `true` in paper mode.
14
+ Logs/QR appear on stderr. `events --follow` and `logs` explicitly stream JSON lines.
15
+ Use `--network testnet` during testing; never silently change to mainnet.
16
+
17
+ ## Paper first, then fund and go live
18
+
19
+ Start every strategy in paper mode: `agent-cli --paper ...`, `config set mode
20
+ paper`, or `run --paper`. Paper mode runs against real mainnet Hyperliquid
21
+ public market data (info + WS l2Book/trades/bbo, meta, funding) and never signs
22
+ or submits anything — no Privy session, `approveAgent`, or deposit is needed.
23
+ `order`/`cancel`/`modify`/`leverage` keep the same validation, risk limits,
24
+ builder fee and audit trail; a local simulator fills them (book-walking market
25
+ orders, resting limits, reduce-only, TP/SL, fees, funding, margin/liquidation
26
+ approximation). State is restartable under `~/.bloxwap/paper/`; `paper summary`
27
+ reports PnL/fees/funding, `paper reset --yes` clears it. Envelopes and events
28
+ carry `mode`/`paper`, paper state never mixes with live state, and going live
29
+ requires `config set mode live --yes`. Only after the paper results are proven,
30
+ continue with live onboarding below and real funding.
31
+
32
+ ## Onboarding sequence
33
+
34
+ 1. The user owns all settings and chooses their own Privy app or dedicated EOA
35
+ agent; no wallet or credentials are bundled. For Privy, set `signerType` to
36
+ `privy` and configure the app ID and `privyAppSecretRef`. For EOA, set
37
+ `signerType` to `eoa` and configure `eoaKeyRef`, e.g. `env:BLOXWAP_EOA_KEY`
38
+ or a mode-0600 `file:` path.
39
+ The user creates the key and sets the secret outside the conversation on their
40
+ own machine or runner. Never accept raw keys in CLI input or use the master EOA
41
+ as the agent. Master-wallet approval always remains in the user's external wallet.
42
+ The default Bloxwap builder is `0x71b09A08257078A4d642F7Dd7315e656c837329a`,
43
+ with `f=0` (no builder fee). The default referral code is `BLOXWAP`; override
44
+ with `config set referralCode` or `BLOXWAP_REFERRAL_CODE`. Optional non-zero
45
+ builder fees use `config set builder.address` / `config set builder.fee` or
46
+ `BLOXWAP_BUILDER_ADDRESS` / `BLOXWAP_BUILDER_FEE`.
47
+ 2. Run `init --master-address 0x... --network testnet`. Show the returned approval
48
+ payload/deeplink/QR. The user signs in their master wallet; submit only the
49
+ resulting signature with `init --signature 0x...`. After agent approval, init
50
+ applies the configured referral if the account has none and leaves existing
51
+ referrals unchanged. Builder approval is needed only for a non-zero configured
52
+ fee. Continue only after `approved:true`.
53
+ 3. Run `fund --amount 10 --origin-chain 42161`. Show `qrAscii`/deposit address,
54
+ origin chain/token, minimum, fees, expected received amount and expiry. On
55
+ testnet, do not treat the default Arbitrum mainnet chain/token as a test route:
56
+ use an explicitly supported test chain/token and `originDecimals`, or the
57
+ credential-gated CI harness with mocked Relay and mocked Hyperliquid orders.
58
+ If no test route is known, stop funding and report the missing route. The user
59
+ transfers the quoted origin token. If `signatureSteps` require signatures,
60
+ show the exact payload and submit each via `deposit` in returned order.
61
+ 4. Poll `status` until each active deposit is `settled`, for at most 12 polls
62
+ or 5 minutes, whichever comes first. Start with 1-second delays, double to a
63
+ 15-second cap, and stop with an explicit pending report if the budget expires.
64
+ Settlement requires Relay success and Hyperliquid balance receipt. Stop on
65
+ failed/refunded deposits and explain their status. Do not place orders while
66
+ any deposit is awaiting funds or pending.
67
+ 5. Run `run --detach`, then monitor `events --follow --since SEQ`. Persist the
68
+ last handled sequence; replay after reconnect. An unfilled or rejected order
69
+ remains incomplete: do not claim the requested trade succeeded. A fill updates the trading
70
+ plan, an error follows the catalog below, and expiry warnings prompt rotation
71
+ using external master-wallet approval.
72
+
73
+ ## Completion and approval boundaries
74
+
75
+ Read this skill and query schemas before acting. Keep a progress record with the
76
+ network, current stage, deposit IDs, last event sequence and order cloid/oid;
77
+ record public IDs only. Missing selected-signer settings, a wallet signature,
78
+ funding route or settled balance is a blocked stage. Report the exact next action
79
+ without requesting any secret in chat or moving to the next stage. Repeat `init`
80
+ to resume persisted approvals rather than creating another agent. An `ok:true`
81
+ transport envelope does not imply exchange acceptance: inspect `data.result` and
82
+ reconcile `orders`/`events` after uncertain mutations. Never retry an order with
83
+ a new cloid until the original intent has been reconciled.
84
+
85
+ For EOA rotation, the user sets a new local key and supplies only its reference
86
+ with `rotate --eoa-key-ref env:NEW_EOA_KEY`. For either signer, verify
87
+ `swapped:true` before asking the external wallet to sign old agent revocation. Require `oldRevoked:true` before claiming rotation complete.
88
+ `revoke` immediately disables local signing; only `exchangeRevoked:true` confirms
89
+ that the signed exchange revocation was submitted. Inspect `status` to verify the
90
+ agent is absent from exchange approvals. Cancel outstanding orders before final
91
+ revocation, and report any cancellation or cleanup failure explicitly.
92
+
93
+ ## Commands and example envelopes
94
+
95
+ Examples show representative `data`, not live balances or service promises.
96
+ Full inputs/outputs are discoverable with `schema`; amounts/prices are strings.
97
+
98
+ | Input | Example output |
99
+ | --- | --- |
100
+ | `--help` | `{"ok":true,"data":{"commands":[{"name":"status","description":"Read account status"}],"globalFlags":["--json","--config","--network","--pretty"]}}` |
101
+ | `schema order` | `{"ok":true,"data":{"input":{"type":"object"},"output":{"oneOf":[]}}}` (actual schemas include properties) |
102
+ | `config get network` | `{"ok":true,"data":"testnet"}` |
103
+ | `config set limits.maxLeverage 5` | `{"ok":true,"data":{"version":1,"limits":{"maxLeverage":5}}}` |
104
+ | `config validate` | `{"ok":true,"data":{"valid":true,"version":1}}` |
105
+ | `init --master-address 0x...` | `{"ok":true,"data":{"approved":false,"requiresSignature":true,"approvals":{"agent":{"typedData":{}}},"qrAscii":"..."}}` |
106
+ | `fund --amount 10 --no-qr` | `{"ok":true,"data":{"depositId":"...","depositAddress":"0x...","expectedReceived":"100000000","builderFeeRate":"0%","builderAddress":"0x71b09A08257078A4d642F7Dd7315e656c837329a","state":"awaiting_funds","qrAscii":null}}` |
107
+ | `deposit --deposit-id ID` | `{"ok":true,"data":{"depositId":"ID","steps":[{"id":"step:0","requiresSignature":true,"payload":{}}]}}` |
108
+ | `deposit --deposit-id ID --step-id step:0 --signature 0x...` | `{"ok":true,"data":{"depositId":"ID","steps":[]}}` |
109
+ | `status` | `{"ok":true,"data":{"balance":{"accountValue":"100"},"agent":{"approved":true,"daysRemaining":"179"},"deposits":[],"policy":{"id":"...","version":"2"},"runner":{"pid":"123"}}}` |
110
+ | `balance` | `{"ok":true,"data":{"accountValue":"100","accountValueUnits":"10000000000","withdrawable":"96","marginUsed":"4"}}` |
111
+ | `market --coin BTC` | `{"ok":true,"data":{"coin":"BTC","asset":"0","szDecimals":"5","maxLeverage":"40","mid":"20000"}}` |
112
+ | `positions` | `{"ok":true,"data":[{"coin":"BTC","size":"0.001","entryPrice":"20000","leverage":"5","marginMode":"cross"}]}` |
113
+ | `orders` | `{"ok":true,"data":[{"coin":"BTC","oid":"123","sz":"0.001","limitPx":"20000","side":"B"}]}` |
114
+ | `order --json '{"coin":"BTC","side":"buy","size":"0.001","price":"20000","tif":"Gtc","cloid":"0x11111111111111111111111111111111"}'` | `{"ok":true,"data":{"result":{"status":"ok","response":{"data":{"statuses":[{"resting":{"oid":123}}]}}},"builderFeeRate":"0%","builderAddress":"0x71b09A08257078A4d642F7Dd7315e656c837329a","cloid":"0x..."}}` |
115
+ | `order --json '{"coin":"BTC","side":"sell","size":"0.001","type":"market","slippage":0.01,"reduceOnly":true}'` | `{"ok":true,"data":{"result":{"status":"ok","response":{"data":{"statuses":[{"filled":{"oid":123}}]}}}}}` |
116
+ | `cancel --oid 123` or `cancel --all` | `{"ok":true,"data":{"cancelled":["123"],"result":{"status":"ok"}}}` |
117
+ | `modify --json '{"modifications":[{"oid":123,"price":"20100","size":"0.001"}]}'` | `{"ok":true,"data":{"status":"ok"}}` |
118
+ | `leverage --coin BTC --leverage 5 --mode isolated` | `{"ok":true,"data":{"status":"ok"}}` |
119
+ | `run --detach` | `{"ok":true,"data":{"pid":123,"startedAt":1700000000000,"network":"testnet"}}` |
120
+ | `events --since 12 --types '["fill"]'` | `{"ok":true,"data":[{"seq":13,"timestamp":"2026-01-01T00:00:00.000Z","type":"fill","data":{"tid":1}}]}` |
121
+ | `events --follow` | `{"seq":13,"timestamp":"2026-01-01T00:00:00.000Z","type":"fill","data":{"tid":1}}` (one line per event) |
122
+ | `logs --follow --level warn` | `{"level":"warn","requestId":"...","message":"Risk rejected","time":"..."}` (JSON lines) |
123
+ | `paper reset --yes` | `{"ok":true,"data":{"paper":true,"mode":"paper","reset":true,"startingBalance":"10000"},"mode":"paper","paper":true}` |
124
+ | `paper summary` | `{"ok":true,"data":{"paper":true,"mode":"paper","equity":"10000","netPnl":"0","feesPaid":"0","fundingPaid":"0","trades":0,"positions":[]}}` |
125
+ | `order --paper --json '{"coin":"BTC","side":"buy","size":"0.001","type":"market"}'` | `{"ok":true,"data":{"result":{"status":"ok","response":{"data":{"statuses":[{"filled":{"oid":1,"totalSz":"0.001","avgPx":"20000","status":"filled"}}]}}},"builderFeeRate":"0%","builderAddress":"0x71b09A08257078A4d642F7Dd7315e656c837329a","cloid":null},"mode":"paper","paper":true}` |
126
+ | `run --paper --detach` | `{"ok":true,"data":{"pid":123,"startedAt":1700000000000,"network":"mainnet","paper":true}}` |
127
+ | `rotate` then `rotate --signature 0x...` | `{"ok":true,"data":{"oldAgent":"0x...","newAgent":"0x...","swapped":true,"oldRevoked":false,"revokeApproval":{}}}` |
128
+ | `rotate --revoke-signature 0x...` | `{"ok":true,"data":{"swapped":true,"oldRevoked":true}}` |
129
+ | `revoke --cancel-orders` | `{"ok":true,"data":{"locallyRevoked":true,"exchangeRevoked":false,"requiresSignature":true,"approval":{}}}` |
130
+ | `revoke --signature 0x...` | `{"ok":true,"data":{"locallyRevoked":true,"exchangeRevoked":true}}` |
131
+ | `audit --intent ID` | `{"ok":true,"data":[{"intentId":"ID","stage":"decision","data":{"allowed":true},"previousHash":"...","hash":"..."}]}` |
132
+ | `skill install --target codex` | `{"ok":true,"data":{"target":"codex","path":".../agent-cli/SKILL.md","version":"0.3.0"}}` |
133
+
134
+ Before an order, query `market --coin BTC` for `mid`, `szDecimals`, asset and
135
+ market leverage ceiling. Compute size/notional with decimal strings/bigints,
136
+ using the user-approved limit or the bounded IOC execution price. A valid schema
137
+ alone does not establish that an order is tradable or within the budget.
138
+
139
+ Use `--intent-id ID --intent "reason"` on trading actions to connect the user's
140
+ reasoning to the audit. Keep cloid stable when retrying a known order intent.
141
+ For TP/SL use `type:"tp"|"sl"` and `triggerPrice` with size/price/reduceOnly;
142
+ market orders use an explicit slippage-bounded IOC, not an unbounded market order.
143
+
144
+ ## Error recovery
145
+
146
+ | Code | Action |
147
+ | --- | --- |
148
+ | RATE_LIMIT, NETWORK_ERROR | At most 3 read retries with exponential backoff; for uncertain mutations, reconcile order state/cloid before retrying. Stop and report unresolved results |
149
+ | NONCE_COLLISION | Retry using a newly issued nonce; inspect a stale lock if persistent |
150
+ | DEPOSIT_PENDING | Poll status until settled; stop on terminal funding failure |
151
+ | RUNNER_NOT_RUNNING | Start runner or use configured direct fallback |
152
+ | INSUFFICIENT_MARGIN | Reduce exposure or request authorized funding |
153
+ | POLICY_REJECTED | Stop and revise intent within limits; do not bypass policy |
154
+ | AGENT_EXPIRED | Rotate with master-wallet approval |
155
+ | AGENT_NOT_APPROVED | Complete init/approval or explain revocation |
156
+ | INVALID_SIZE, INVALID_PRICE | Correct input using market precision |
157
+ | UNKNOWN_MARKET | Refresh metadata; use an allowed market |
158
+ | ORDER_NOT_FOUND | Refresh orders before changing intent |
159
+ | CONFIG_INVALID | Correct configuration/input; never insert secrets |
160
+ | UPSTREAM_ERROR, INTERNAL | Stop, inspect redacted details/logs and report failure |
161
+
162
+ ## Gotchas
163
+
164
+ HyperCore perps USDC uses **8 decimals**; EVM USDC uses **6**. Preserve strings and
165
+ bigints. Some deposits require **two distinct signatures**; resume stored steps
166
+ rather than restarting the route. Agent expiry is at most **180 days**. Never
167
+ ask for, paste, log or import a master private key or seed. EOA agent keys are
168
+ accepted only through user-configured local references, never command input.
169
+ The agent is trade-only; local limits include markets, size/notional, leverage,
170
+ daily loss and open orders — in paper mode these limits are enforced exactly the
171
+ same way. Privy sees an L1 action hash, so it cannot independently inspect
172
+ notional/action contents; EOA agents have no remote Privy policy. Hyperliquid
173
+ agent permissions and local checks enforce those boundaries for both signers. State is always `~/.bloxwap`, env prefix `BLOXWAP_`; paper
174
+ state is `~/.bloxwap/paper/` and is never read by live commands (or vice
175
+ versa). Envelopes and events always state `mode`/`paper`.
176
+
177
+
178
+ ## Verification boundaries
179
+
180
+ Offline skill tests validate the documented command examples against CLI schemas.
181
+ Mocked lifecycle tests exercise resumable approvals, pending funding, events
182
+ and failure handling. These checks do **not** prove a live agent or
183
+ exchange run. The nightly testnet lifecycle uses only a company-owned disposable
184
+ CI master account and separate test Privy app, live Privy and Hyperliquid
185
+ approvals/revocation, and explicitly mocked Relay plus mocked Hyperliquid orders
186
+ that never reach the exchange. The dedicated master account still needs a positive
187
+ test USDC balance because live approvals require prior test collateral.
188
+ The same harness supports a caller-controlled external wallet approval adapter
189
+ on a clean QA runner; its private key stays in that wallet. It never transfers
190
+ real funds. Missing CI credentials fail the job; a skipped or
191
+ mocked test must never be reported as live validation. Record the workflow run,
192
+ commit, lifecycle report, event and audit artifacts before claiming a testnet pass.
193
+ See `docs/agent-workflow.md` and `docs/testnet.md` in the repository for setup.