Plans & simulations
developerTyped plans: compilation, the frozen plan hash, idempotency key, 15-minute expiry, the run state machine, and the honest simulation lifecycle where no on-chain simulation runs while signing is disabled.
A plan (ConsolePlan in @hiss/core) is the frozen, typed output of compiling a candidate intent. It carries the resolved chain, contract, selector, asset, and amount — all from deterministic resolvers, never from model text — plus an idempotency key, an expiry, and a plan hash that freezes the whole payload.
Compile and freeze
- Plan hash. The compiler serializes the plan with key-sorted JSON and hashes it. Any later mutation of a critical field invalidates the hash — the security kernel re-verifies it before a plan may be reviewed or handed to a wallet. See the security model.
- Idempotency key. Each plan carries a caller-generated key unique per user and action scope, so retries reconcile to one run rather than duplicating it.
- Expiry. Prepare actions carry
planTtlSeconds— a default of 15 minutes. Past itsexpiresAtEpocha value-bearing plan is expired and the kernel blocks it. Pure reads do not expire.
Run states
A run walks a state machine (in compiler.ts): DRAFT → RESOLVING_INTENT → VALIDATING → VALIDATED → SIMULATING → SIMULATED → AWAITING_REVIEW, and — only when signing is separately enabled — APPROVED_FOR_WALLET onward to SUBMITTED, CONFIRMED, and COMPLETED. A blocked action lands in BLOCKED; a failed validation in REJECTED; a lapsed plan in EXPIRED.
Simulation lifecycle
POST /api/console/plans/:id/simulate records the simulation lifecycle for a prepared run and advances it toward AWAITING_REVIEW.
Once a run reaches AWAITING_REVIEW it is ready for the approval inbox. Nothing has been signed and nothing has been sent.