Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ apps/*/log_*.json

# Local runtime config files
config/

# Local live supervisor artifacts
logs/live-supervisor/
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Apps:
- `apps/bot`: Node order-fulfillment and rebalance bot for matching profitable orders, collecting owned orders, completing receipts and withdrawals, and rebalancing pool exposure.
- `apps/interface`: Browser interface for CCC wallet connection, conversion previews, transaction completion, signing, sending, and confirmation.
- `apps/sampler`: Mainnet sampling utility that writes historical iCKB exchange-rate CSV output.
- `apps/supervisor`: Deterministic live testnet supervisor for bounded bot/tester stress cycles, ignored artifacts, and incident bundles.
- `apps/tester`: Node simulator that creates random conversion orders to exercise the order and conversion flows.

The Node app packages (`@ickb/bot`, `@ickb/sampler`, and `@ickb/tester`) publish their built entrypoints for distribution, but the supported reusable API surface lives in the packages below. `@ickb/interface` is a deployable browser app package and does not expose a library entrypoint.
Expand Down Expand Up @@ -91,6 +92,29 @@ If you add a new direct `@ckb-ccc/*` dependency to any stack package, add the ma

If you need to update or save the shared CCC baseline, use `forks/phroi_forker/repo/` directly. `forks/ccc/pin/manifest` is the source of truth for the shared upstream refs.

## Live Testnet Supervisor

Build the local CCC fork, shared packages, live apps, and supervisor, provide ignored bounded configs, then run the supervisor from the repo root:

```bash
pnpm forks:ccc
pnpm --filter @ickb/utils --filter @ickb/dao --filter @ickb/core --filter @ickb/order --filter @ickb/sdk --filter @ickb/node-utils build
pnpm --filter ./apps/bot build
pnpm --filter ./apps/tester build
pnpm --filter @ickb/supervisor build
pnpm live:supervisor
```

By default the supervisor uses ignored `config/bot-testnet.json` and `config/tester-testnet.json`, writes artifacts under ignored `logs/live-supervisor/<run-id>/` paths, and runs deterministic bounded bot/tester commands only. It does not patch, verify, rebuild, relaunch, or invoke an LLM; external loops and operators consume `summary.json` between runs.

For repeated bounded invocations, keep loop-owned options before `--` and supervisor options after it:

```bash
pnpm live:supervisor:loop -- --scenario standard-cycle --max-cycles 1
```

Explicit repeatable `--target-outcome` requests become bounded coverage contracts: if `--max-cycles` ends before they are observed, the supervisor writes a logical incident for external review. The supervisor treats public testnet iCKB deposits, receipts, and orders as observable stress surface, but only bot/tester-owned state from the supplied configs is treated as spend authority.

## Licensing

This source code, crafted with care by [Phroi](https://phroi.com/), is freely available on [GitHub](https://github.com/ickb/stack/) and it is released under the [MIT License](./LICENSE).
2 changes: 0 additions & 2 deletions apps/interface/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import { defineConfig } from "vite";

const monorepoRoot = fileURLToPath(new URL("../..", import.meta.url));

// Local CCC iteration resolves built output from forks/ccc/repo, so the
// interface no longer needs the old raw-fork-source Babel/shim escape hatches.
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
Expand Down
69 changes: 69 additions & 0 deletions apps/supervisor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# iCKB Live Supervisor

The supervisor is a deterministic operator app for funded testnet validation. It runs bounded bot/tester app processes, classifies known outcomes without LLM involvement, records ignored artifacts, and stops with an incident bundle on unknown or unsafe outcomes. It does not patch, verify, rebuild, relaunch, or invoke an LLM; operators and external loops consume `summary.json` between runs.

## Run

Build the local CCC fork, shared packages, live apps, and supervisor first:

```bash
pnpm forks:ccc
pnpm --filter @ickb/utils --filter @ickb/dao --filter @ickb/core --filter @ickb/order --filter @ickb/sdk --filter @ickb/node-utils build
pnpm --filter ./apps/bot build
pnpm --filter ./apps/tester build
pnpm --filter @ickb/supervisor build
```

Run from the repo root:

```bash
pnpm live:supervisor
```

By default this uses `config/bot-testnet.json` and `config/tester-testnet.json`. Configs must be ignored JSON files and should keep `maxIterations: 1`. The supervisor passes config paths to the existing app env names and does not print config contents.

## Artifacts

Default artifacts live under `logs/live-supervisor/<run-id>/`, which is ignored by git. Each run writes:

- `supervisor.ndjson`: concise supervisor events.
- `cycle-<n>-<actor>.stdout.ndjson` and `.stderr.log`: bounded app-process evidence for that actor.
- `cycle-<n>-<actor>.command.json`: redacted command shape and exit status.
- `cycle-<n>-incident.json`: written only on unknown, unsafe, unsupported, or unmet explicit coverage outcomes.
- `summary.json`: aggregate outcomes, coverage ledger, tx hashes by outcome, and public-vs-owned state assumptions.

The supervisor treats public testnet iCKB deposits, receipts, and orders as observable scenario surface. It does not count public state as bot/tester-owned inventory or as permission to mutate unrelated cells.

## Scenario Coverage

The default planner prefers under-covered safe outcomes over repeating the same known-good path. Supported selectors are:

```bash
--scenario auto|standard-cycle|tester-only|bot-only|tester-fresh-skip-two-pass
--tester-scenario auto|random-order|sdk-conversion|extra-large-limit-order|multi-order-limit-orders|two-ckb-to-ickb-limit-orders|all-ckb-limit-order|ickb-to-ckb-limit-order|two-ickb-to-ckb-limit-orders|mixed-direction-limit-orders|dust-ckb-conversion|dust-ickb-conversion
--tester-fee <n>
--tester-fee-base <n>
--target-outcome <outcome>
```

Coverage goals never override stop conditions. If a requested scenario cannot be reached through safe supervisor/test-harness controls, the supervisor writes an incident instead of mutating funded configs in place or forcing tx-bearing paths.

Explicit repeatable `--target-outcome` values are coverage contracts for the bounded run. If `--max-cycles` is reached before observing them, the supervisor writes a logical `unmet_coverage_goal` incident. Default coverage goals still steer the planner, but they are best-effort and do not make a bare one-cycle run fail. `--stop-after-tx-count` remains a successful operator stop even if explicit coverage remains unmet.

`--tester-scenario` is passed to the tester as `TESTER_SCENARIO`. When it is left as `auto`, `--target-outcome tester_conversion_created` steers the tester to `sdk-conversion`, the SDK conversion-builder selector. Use `ickb-to-ckb-limit-order` for iCKB withdrawal-through-LO coverage. Use `sdk-conversion` when the intended behavior is the SDK conversion builder, including direct conversions that do not create limit orders, `multi-order-limit-orders` for any funded two-order raw limit-order type, `two-ckb-to-ickb-limit-orders`, `two-ickb-to-ckb-limit-orders`, or `mixed-direction-limit-orders` for a specific two-order transaction, and `extra-large-limit-order` to stress non-interface users placing large raw limit orders. An explicit `--tester-scenario` overrides target-outcome steering.

`tester-fresh-skip-two-pass` runs the same tester config twice in one supervisor cycle. Pass 1 uses `multi-order-limit-orders` to create any funded multi-order transaction; pass 2 leaves `TESTER_SCENARIO=auto` and is expected to classify `tester_fresh_order_skip` when the same key still owns a fresh matchable order. Artifacts use `tester-pass-1` and `tester-pass-2` labels so the two passes do not overwrite each other.

`--tester-fee` and `--tester-fee-base` are tester-owned raw limit-order fee controls. Defaults stay `1 / 100000` (0.001%). When provided, the supervisor passes them only to the tester as `TESTER_FEE` and `TESTER_FEE_BASE`; `sdk-conversion` keeps using SDK-owned fee defaults for any order remainder.

## External Loops

Keep long-running policy outside this app. A loop or human operator should run bounded supervisor commands, read only `summary.json`, and decide whether to continue, back off, stop for inspection, or patch code. This keeps the live harness deterministic and keeps LLM/watch logic outside the funded actor process boundary.

The KISS watcher script runs one deterministic supervisor invocation per child output directory and prints one summary-only line per run:

```bash
node scripts/ickb-supervisor-loop.mjs --max-runs 1 --stable-limit 2 --backoff-seconds 0 -- --scenario standard-cycle --max-cycles 1
```

Loop-owned options go before `--`; supervisor options go after `--`. If using `pnpm live:supervisor:loop`, keep loop-owned options before the first `--` so they are not passed through to the supervisor. The loop stops on supervisor nonzero exit, incident artifacts listed in `summary.json`, any tx hash, a new outcome after the first run, repeated no-progress signatures, or `--max-runs`.
51 changes: 51 additions & 0 deletions apps/supervisor/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"name": "@ickb/supervisor",
"version": "1001.0.0",
"description": "Deterministic iCKB testnet live supervisor",
"keywords": [
"ickb",
"ckb",
"testnet",
"supervisor"
],
"author": "phroi",
"license": "MIT",
"homepage": "https://ickb.org",
"repository": {
"type": "git",
"url": "https://github.com/ickb/stack"
},
"bugs": {
"url": "https://github.com/ickb/stack/issues"
},
"sideEffects": false,
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"scripts": {
"test": "vitest",
"test:ci": "vitest run",
"build": "pnpm clean && tsc -p tsconfig.build.json",
"lint": "eslint ./src",
"clean": "rm -fr dist",
"clean:deep": "rm -fr dist node_modules",
"start": "node dist/index.js"
},
"files": [
"dist",
"src"
],
"publishConfig": {
"access": "public",
"provenance": true
},
"devDependencies": {
"@types/node": "catalog:"
}
}
Loading
Loading