> For the complete documentation index, see [llms.txt](https://nytshift.gitbook.io/nytshift-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://nytshift.gitbook.io/nytshift-docs/policy-control-and-incident-response/portfolio-reconciliation.md).

# Portfolio reconciliation

## Purpose

NIGHTSHIFT retains a bounded local capital-state checkpoint so a venue reconnect can be compared with the last accepted orders, fills, positions, funding and account totals. The checkpoint is forensic/recovery evidence; the venue remains authoritative.

Default path:

* Windows: `%USERPROFILE%\.nightshift\data\portfolio-reconciliation-v1.json`
* Other platforms: `~/.nightshift/data/portfolio-reconciliation-v1.json`

The top-level portfolio key is a 64-character opaque digest. The file contains no account address, key, token, endpoint or signer capability.

## Health interpretation

`/api/health` exposes only:

* `portfolioReconciliationState`: `ready` when the checkpoint is structurally readable, `corrupt` otherwise.
* `portfolioReconciliationAccounts`: retained opaque portfolio count.
* `portfolioReconciliationReady`: portfolios whose latest required snapshot coverage converged.
* `portfolioReconciliationDegraded`: portfolios with stale, out-of-sequence or incomplete evidence.
* `portfolioReconciliationDivergences`: retained bounded recovery/drift records.
* `portfolioReconciliationUpdatedAtMs`: last atomic store update, or `null` before first persistence.
* `portfolioReconciliationIntervalMs`: validated configured interval between successful configured-account reads.
* `portfolioReconciliationMaxRemoteAgeMs`: maximum accepted age of the current capital snapshot.

A readable empty store is healthy infrastructure, not proof that any account has reconciled. When all earlier execution prerequisites pass, `/api/execution/status` reads the exact configured Hyperliquid account, derives an opaque account/network ID, discovers all perp DEXs and requires the latest generation to be `ready`. Review, submit and policy-bound automation inherit the same gate.

The authenticated terminal Safety panel exposes only generation, account mode, balance-authority label and aggregate DEX coverage. It never receives the account address from the portfolio checkpoint.

## Hyperliquid configured-account workflow

1. Discover the complete primary/HIP-3 DEX set through the strict shared `perpDexs` parser, then bind every active sparse slot to the matching `allPerpMetas.collateralToken`. Additive, missing or malformed DEX/collateral metadata aborts the attempt.
2. Read timestamped `clearinghouseState` and `frontendOpenOrders` for every DEX. One failed DEX makes current capital coverage incomplete.
3. Read bounded historical orders, page unaggregated fills and funding, and query exact `orderStatus` for every locally active order missing from the current open-order set. Spot rows returned by shared history endpoints are excluded; malformed history makes order coverage bounded.
4. Normalize complete `spotMeta` token identity and borrow/lend reserve oracle rows. Standard non-USDC DEX state and HIP-3 fee/PnL/funding units are converted through the DEX collateral token. Missing fee-token identity or reserve oracle makes that rail unavailable.
5. Detect `userAbstraction`. Standard mode uses complete per-DEX perpetual margin. Unified values the active DEX collateral-token set from `spotClearinghouseState`. Portfolio Margin values reserve-eligible assets and subtracts debt. Holds and used DEX margin reduce conservative free collateral; unrelated Unified balances remain excluded and visible only as an aggregate ignored count.
6. Reconcile and atomically persist the generation. A complete result caches for the configured interval; a failure retries as a reconnect within at most five seconds.

Defaults are `NIGHTSHIFT_PORTFOLIO_RECONCILIATION_INTERVAL_MS=30000` and `NIGHTSHIFT_PORTFOLIO_MAX_REMOTE_AGE_MS=30000`. Both accept 5,000–300,000 ms and the freshness ceiling must be at least the interval. The default interval budgets the complete current DEX fan-out below Hyperliquid's documented aggregate IP weight limit. Invalid values make health unsafe.

## Recovery rules

1. Keep execution disabled.
2. Preserve the checkpoint and logs; do not edit order or position state by hand.
3. If the venue snapshot is old or out of sequence, acquire a new complete venue snapshot. Never move the local remote-observation clock backwards.
4. If an open order disappears, query exact `orderStatus` by CLOID/order ID and page matching fills. Do not mark it canceled and do not resubmit.
5. If position/account coverage is unavailable, preserve the last state, show degraded health and restore the missing provider rail.
6. After a complete boot/reconnect snapshot converges, inspect new fixed-code divergences before reopening any execution gate.
7. For Unified or Portfolio Margin, never substitute perps margin for total equity. `SPOT_CLEARINGHOUSE_UNAVAILABLE`, `SPOT_CLEARINGHOUSE_SCHEMA_INVALID`, `SPOT_COLLATERAL_BALANCE_UNAVAILABLE`, `SPOT_METADATA_UNAVAILABLE`, `SPOT_METADATA_SCHEMA_INVALID`, `COLLATERAL_METADATA_UNAVAILABLE`, `COLLATERAL_ORACLE_UNAVAILABLE` or `COLLATERAL_MARGIN_SCHEMA_INVALID` keeps execution disabled. Do not manually coerce a missing collateral identity/oracle into USDC.
8. A fresh review must also read `activeAssetData`. If active leverage differs from the request, set leverage deliberately at the venue and start a new review. Never edit the ticket, infer Portfolio Margin borrow headroom or override maximum order size/available capacity locally.

## Backup and restore

The normal local backup includes `data/portfolio-reconciliation-v1.json` only when the file exists.

```powershell
pnpm backup:create
pnpm backup:list
pnpm backup:verify -- <backup-id>
pnpm local:stop
pnpm backup:restore -- <backup-id>
pnpm local:start
pnpm local:health
```

Verification rejects undeclared fields, invalid checkpoint schemas, account-address/key/token material, duplicate identity, malformed state and checksum drift. Restore remains offline and preserves displaced state under `~/.nightshift/recovery/`.

## Incident classes

* `REMOTE_SNAPSHOT_TOO_OLD`: provider observation exceeds the configured age or future-clock allowance.
* `STALE_REMOTE_SNAPSHOT`: provider observation precedes the last accepted remote timestamp.
* `LOCAL_OPEN_ORDER_MISSING`: a locally non-terminal CLOID is absent from a complete open-order snapshot; exact status reconciliation is mandatory.
* `ORDER_STATE_DRIFT`: venue order state differs from the retained state.
* `LOCAL_POSITION_MISSING`: a complete venue position snapshot proves the retained position no longer exists.
* `POSITION_STATE_DRIFT`: size, entry, mark, notional, PnL, liquidation, leverage, margin or funding changed.
* `SNAPSHOT_COVERAGE_INCOMPLETE`: at least one required rail is unavailable; the state is degraded.

Recovery records explain convergence. They are not permission to retry, sign, cancel or trade.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://nytshift.gitbook.io/nytshift-docs/policy-control-and-incident-response/portfolio-reconciliation.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
