Skip to content

Resolve Predict predeploy audit items#1097

Merged
0xaslan merged 39 commits into
mainfrom
at/predict-audit-sweep
Jul 3, 2026
Merged

Resolve Predict predeploy audit items#1097
0xaslan merged 39 commits into
mainfrom
at/predict-audit-sweep

Conversation

@0xaslan

@0xaslan 0xaslan commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Resolve the Predict predeploy audit campaign end to end: Propbook canonical rebinding, PLP price circuit-breaker removal (P-1), settled-sweep liveness acceptance, coverage-gap closures, the mini-audit sweep that curated new findings into the tracker, and seven hygiene batches (dedup/layout, role-order signatures, parked-item adjudications, test coverage, abort-code split, H-2/H-3/H-4/G-1 resolutions).
  • Extend C-4 with the dust-mark overflow boundary (untracked u64-cast abort + supply ratchet) exposed by the P-1 circuit-breaker removal, and fix docs/risks.md, which had claimed unimplemented skip/refund drain isolation as shipped behavior since Predict rework: propbook oracle, absolute-tick strikes, async NAV/LP, passive settlement, indexers #1071.
  • Consolidate the team development system into the tracked tree: predeploy/README.md system map (authority order + lifecycle loops), response-policies.md register of settled tail-state decisions (RP-1..RP-8), experiments.md harness experiment ledger (E1–E6, each with a driving ID and a pre-registered decision rule), and the rejected-directions ledger + promoted journal decisions in AGENTS.md. The gitignored design-era journals were extracted into those homes and deleted.
  • Add enforcement: predeploy/check.py cross-reference linter (register pinning tests exist, tracker ID cross-refs resolve, MEASURED claims link evidence, no dead paths — mutation-tested both directions), wired into the review rules and the predict-audit preflight; the audit skill gains register re-verification obligations, a mini depth tier, and the hygiene + polish rule-sweep trios.
  • Resolve H-2: the mint max_cost assert moves into settle_mint_payment, the single fee-decomposition site, so the slippage guard bounds the exact withdrawal by construction; adds a boundary test pair (exact all-in cost passes, one unit below aborts EMintCostAboveMax).
  • Document the batch-7 Block Scholes absence abort codes (EBlockScholesPriceUnavailable / EBlockScholesSVIUnavailable) in the concept docs.

Key decisions

  • Tail-state behavior decisions now live in response-policies.md with reasoning, a risk profile (MEASURED vs BEST-GUESS), pinning tests, and a reopen condition. Removing or weakening any guard requires a duty inventory there — motivated by the P-1 removal, whose sound fairness argument silently dropped the only u64-headroom bound on LP fill math.
  • Authority order codified in the system map: Move source + tests → response/rounding policies → live trackers → AGENTS.md/rules → public docs. Docs describe recorded behavior; a doc claim that leads the code is a finding.
  • The dev system was validated by a zero-context fire drill: a fresh session, given one line and no context, picked up H-2 and completed the full loop (rules loaded, tests before refactor, tracker write-back, linter run) unaided. Its fix is the H-2 commit cherry-picked here.
  • .claude/predict-design/ and .redesign/ are personal scratch only; anything a second person needs to continue work must live in the tracked tree.

Test plan

  • sui move build --path packages/predict --warnings-are-errors — clean at HEAD
  • sui move test --path packages/predict --gas-limit 100000000000 — 367/367
  • python3 packages/predict/predeploy/check.py — cross-references clean (linter itself mutation-tested)
  • python3 .claude/skills/predict-audit/preflight.py — module map + D-id citations resolve
  • propbook/account suites green earlier in the campaign; no changes to those packages since
  • Background multi-agent review of the full PR diff (running; findings will be triaged before merge)

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xct5NpFmALuRtz2tQL18yG

0xaslan and others added 16 commits June 23, 2026 18:24
The [min_plp_price, max_plp_price] band and pool-NAV dust floor in
finish_flush had no on-chain recovery path: an out-of-band frozen mark
bricked the entire flush (valuation, sweeps, rebalance, LP fills) until
package upgrade, including the legitimate 100x-appreciation and
post-drawdown recapitalization cases. The flush mark is the exact NAV,
so any price it produces is fair by construction; the true arithmetic
degeneracies (zero-share supply fill, zero-payout withdraw fill, zero
pool value) are owned by the drain's EInvalidDrainMark guards at the
fill site, which only bind on a pending degenerate head request the
owner can cancel.

- Delete assert_plp_price_in_bounds, its error consts, and the
  min_plp_price/max_plp_price macros; renumber remaining plp abort
  codes contiguously 0-9 (pre-deploy, name-referenced only)
- Repurpose the three CB expected_failure tests into positive flushes
  asserting exact pool NAV at formerly-forbidden marks
- Add EInvalidDrainMark boundary tests for zero-share supply and
  zero-payout withdraw fills, one unit past each boundary
- Drop the now-dead min_bootstrap >= min_withdraw relationship test
  (its only consumer was the deleted dust-band guard)
- Update lp-nav-zero-brick notes, risks.md, and resolve P-1 in
  open-items.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The partial-close floor split computed the removed floor with a
double-floor fraction (mul over a floored close fraction) and derived
the survivor by subtraction, so a max-size leveraged order closed to a
small remainder could leave survivor floor_shares > quantity and abort
order::replacement with EInvalidFloorShares.

Derive the survivor floor directly with a single round-down
mul_div_down(old_floor_shares, remaining_quantity, old_quantity) —
bounded by remaining_quantity whenever F <= Q holds at mint — and set
the removed floor to the conserved difference. That difference equals
ceil(old_floor * close_quantity / old_quantity), bit-identical to the
mul_div_up redeem deduction the old code computed separately, so the
trader-facing redeem_amount is unchanged and the duplicate removed-
floor derivation collapses into one. Both payout-tree atoms (quantity,
floor_shares) remain exactly conserved across the split, preserving
the tree's bit-exact insert/remove round-trip.

- Add a max-size 6x partial-close regression down to one lot: survivor
  quantity == 10_000, floor_shares == 4_166 (= floor(5Q/12 * lot / Q)),
  position present, market backed; red-checked against the old split
- Resolve P-3 in open-items.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Canonical bindings become current accepted bindings instead of insert-only
one-shots. Adds replace_pyth_binding_for_underlying and the atomic
replace_block_scholes_bindings_for_underlying (spot+forward+SVI, one
bs_source_id), with OracleRebound carrying old and new source/object IDs.
No unbind path; source-to-underlying assignment stays sticky across
replacement. Predict already resolves the current binding by underlying at
call time, so it follows a rebind with no contract changes.

Coverage: registry replace/abort/sticky-source tests, Predict pricer
rejects old feeds and follows rebound feeds, and passive settlement
rejects old Pyth and settles on the rebound feed after exact-ms backfill.
README documents the replacement flow, the spot-only recovery path, and
the Pyth backfill runbook; P-4 removed from the predeploy tracker.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolve the S-1 deploy gate as an accepted operational assumption:
exact-timestamp settlement is a monitored sub-minute transient under
testnet operations (~870 settles, zero missing exact prints, zero
manual settles). Evidence, keeper controls, the one stream-channel
incident, and the residual keeper-availability risk are documented in
predeploy/settlement-liveness.md; no contract change is planned.

Add read/observability surface for cadence deployment policy:

- Emit CadenceConfigUpdated from registry::set_cadence_config after
  the stored update (all-zero fields = cadence disabled, matching the
  validated config shapes)
- Expose registry::cadence_config plus public CadenceConfig getters
  (cadence_-prefixed; bare names collide with DeployableMarket getters)
  and a cadence_enabled predicate
- Promote expiry_market::settlement_price to public as user-facing
  terminal protocol state

Known follow-ups: indexer decode struct/handler for
CadenceConfigUpdated, and a getter round-trip test for the new
CadenceConfig read surface.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A cheap pre-audit sweep that surfaces easy cleanups raw (no verify
panels) so deep runs can spend their finding slots on new ground:

- depth:'mini' preset in all three harnesses: maxRounds 1, verifyCap 0
  (findings reported unverified — the operator is the verifier), finder
  effort dropped to medium
- profile:'cleanup' on the orchestrator: only the cleanup-tier lenses
  (surface-area, assertions, architecture) — the inverse of 'security'
- verifyCap now resolved with a typeof-check instead of ||, so an
  explicit 0 no longer silently falls back to the default 60
- SKILL.md: mini row in the depth table + a mini-pass recipe, including
  the feed-forward loop (fix/disposition mini findings, then pass the
  run's findings.json as the deep run's priorAdjudications)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
0xaslan and others added 13 commits July 2, 2026 13:37
Mini cleanup-triage run at b34b0cd (rule-sweep all 11 families +
orchestrator cleanup lenses, depth:mini, operator-verified). Adds:
- P-8: PoolVault.protocol_reserve_balance is accrue-only, no withdraw path
- C-4: LP flush drain hard-aborts on zero-value head request / NAV==0 mark
- Maintainability and Pre-Deploy Hygiene section (H-1..H-3)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A zero-caller public getter is not automatically dead (devInspect/PTB
consumers are invisible to grep) — but exposure intent must be recorded
where it cannot drift. New move.md rule: a public read with no in-repo
consumer names its consumer class in its doc comment; zero callers with
no stated class = unclassified, default delete pre-deploy (add-later is
upgrade-compatible, remove-later is not). The one-way door applies to
`public` only; `public(package)` is not frozen by upgrades.

Promotes the substance of local-journal D003 into committed policy.

Enforcement: surface-area lens reports classify-or-delete instead of
dead; rule-sweep public-api-exposure family checks the doc-comment
classification on the same enumeration (no new family). open-items H-1
reworded to classify-or-delete; package-only stake_config getters moved
to plain cleanup (H-3) since they carry no deploy deadline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…CLAUDE

- move.md: remove three verbatim duplicate rules from General Move
  Patterns (object-binding-before-branch, phase-boundary, emit-after-
  transition) and fold the validate-before-mutate summary into its one
  unique clause (irreversible resources) — the full versions live in
  Validation And Ownership / API Shape. Move the embed-repeated-field-
  group rule up to API Shape; the checklist return-tuple and events
  sections become pointers to the canonical rules.
- unit-tests.md: examples referenced removed APIs (PredictManager,
  pre-extraction oracle::create_test_oracle / predict::mint shapes);
  rewritten as schematic examples using the current account/registry/
  propbook world.
- indexer.md: the "Recommended Indices" all exist via the 2026-02-03
  ticker-performance migration — relabel so agents don't re-add them.
- CLAUDE.md: path-scoped rule injection is now native Claude Code
  behavior (observed live with empty hooks config); keep read-it-
  yourself as the baseline instruction, correct the mechanism claim.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Routing: add predict-harness.md path rule and the harness-strategy
  manual trigger (present in CLAUDE.md, missing here); correct the
  rule-injection mechanism claim (native in recent Claude Code, absent
  in Codex — read-it-yourself stays the baseline).
- Repo layout: list all eight crates (predict-* and oracle-* stacks
  were missing).
- Predict rework: the consolidation landed on main; the "Rust crates
  need rewiring" claim was stale — the predict/oracle crates exist and
  handle the async-LP events. Replaced with the verified current state:
  event-parity audit still open (handlers for removed events remain;
  PoolValued and the refund events have no handler).
- Settled decisions: add the static-floor knockout entry and promote
  D025 (no redeem ask bound), D026 (strike math stays u64), D031 (no
  oracle deviation guards) from the local decision journal into this
  committed ledger. Clears all three predict-audit preflight warnings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three new mechanical families closing the categories no harness swept:
- signature-shape: input ordering by role, wide same-typed primitive
  runs, receiver-syntax accessor naming — with the mandatory warning
  that Move signature reorders silently break positional TS PTB callers
  (scripts/harness/sims) at runtime.
- module-layout: visibility-group function ordering, copyright header +
  module-doc presence, naming conventions (one finding per module).
- comment-hygiene: narrating/stale comments, math comments matching the
  called function and rounding direction, missing public-API/config docs.

Rule sweep is now 14 families; SKILL.md counts updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mechanical, behavior-preserving fixes from the mini-audit triage + the
hygiene sweep (all suites green: predict 356, propbook 54, account 11):

- lp_book: remove_for_recipient now peeks ownership then delegates to
  remove() instead of cloning it; RequestEntry gains a struct doc naming
  the per-queue amount unit.
- plp: settled-vs-live dispatch shared by value_expiry and
  rebalance_expiry_cash extracted into settle_or_rebalance_expiry.
- propbook registry: bind_block_scholes_surface_to_underlying no longer
  preflights the source/binding asserts bind_oracle re-runs (same
  module, same codes — atomicity makes the preflight valueless).
- strike_exposure: liquidation-candidate loop uses vector do! macro.
- ewma: the thrice-repeated gas-scaling overflow comment and expression
  become one scaled_gas_price helper.
- protocol_config: set_protocol_reserve_profit_share (public) moved out
  of the public(package) group.
- account: read-only getters ordered before share/load_account_mut.
- stake_config: the relational upper > 2*lower check moves from
  config_constants to the owning setter per the Config rule (single-
  value bounds stay); EInvalidBenefitPowers now aborts from
  stake_config and the test pin follows; config_constants codes
  renumbered contiguous; StakeConfig gains a struct doc.
- tests: share_exposure_harness helpers renamed
  create_and_share_exposure_harness (they create AND share).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reorder six package-internal signatures to the move.md input-role order
(objects before primitives; consumed asset values directly after the
receiver). All call sites are in-package or in tests — sweep-verified
zero TypeScript PTB callers, so no off-chain surface moves:

- pricing::load_live_pricer: four feed refs before the id/expiry
  primitives (wrapper + 5 direct test callers updated).
- lp_book::drain: (book, ledger, mark, pool_vault_id, budgets, ctx).
- lp_book::request_supply/request_withdraw: Coin directly after book.
- pool_accounting::receive_expiry_cash: Balance before the id.
- oracle_lane::update/insert_at: the OracleRead before the event id.
- strike_payout_tree::walk_linear: memo before tick_size.

Suites green: predict 356/356, propbook 54/54.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Five patterns the hygiene sweep confirmed are intentional, promoted to
committed rules so future sweeps and agents don't re-flag or "fix" them:
- &AccumulatorRoot is execution context (tail with clock/ctx) — never
  reorder existing public entrypoints; positional TS PTB callers break
  at runtime. Role order applies to new functions.
- emit_* helpers in events/ may mirror event-struct field order.
- init-only private helpers come early with init.
- Constant-like macro funs live at module top, exempt from
  visibility-group ordering.
- Trivial public field getters under a getters header need no
  per-function docs when the struct/fields are documented.

Sweep family texts updated to match (signature-shape, module-layout,
comment-hygiene).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Eight new tests, all through existing fixtures — zero new #[test_only]
source seams (predict 363/363, propbook 55/55, both suites green):

- plp::EMarketNotSettled: rebate claim on a past-expiry market with no
  exact Propbook print aborts at the plp gate.
- predict_account::EExpirySummaryHasOpenPositions: rebate claim with an
  unredeemed position refuses to resolve the summary.
- strike_exposure::EReferenceTickAlreadySet: reachable only through a
  P-4 admin pyth rebind whose replacement feed carries a conflicting
  exact print — exercised via create_and_rebind_oracle.
- registry pause-cap: positive market mint-pause + revoked-cap
  EPauseCapNotValid (mirrors the existing trading-pause pair).
- plp::unstake_deep positive path (new unstake_deep_bundle helper in
  flow_test_helpers): all staked custody returns, stake mirrors zeroed.
- protocol_config::set_ewma_params/set_ewma_enabled positive coverage.
- forward_feed::EWrongSource, completing the per-feed guard symmetry.

Four guards dispositioned as documented defense-in-depth instead of
contrived tests (per unit-tests Rule 12): the market_manager SVI
NotBound assert (forward+SVI bind atomically; forward assert fires
first), both EInvalidDeploymentExpiry asserts (expiry always comes from
next_deployable_market), pricing::ECannotBeNegative (analytically
non-negative inside the |rho|<=1 envelope), and the pyth Lazer parse
guards (no Move constructor for pyth_lazer::Update).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolves the quick parked items per user decisions (predict 363/363,
propbook 55/55, harness + simulations tsc clean):

- Rename to committed conventions, pre-deploy while free:
  create_and_share_expiry_market, create_and_share_builder_code
  (create_and_share rule), set_template_cadence_config (template-setter
  rule) — including TS PTB target strings (harness runtime, simulations
  runtime/sim) and doc/skill references.
- Split EInvalidMarketTickSize: the grid check (zero / off-unit) keeps
  the code; the raw-strike overflow ceiling is now
  EMarketTickSizeTooLarge, with the overflow test repointed.
- Doc lines: OrderMinted/LiveOrderRedeemed builder_code_id field
  contract (none when no builder fee paid — attribution follows the
  fee, applied once in the emit helper); pyth_feed div_ceil us->ms
  rounding direction (<=1ms optimistic, immaterial vs multi-second
  freshness windows).

Adjudicated as won't-fix/settled (recorded in the run dispositions):
loop-assert hoist (no gas win, abort-selection change), emit-helper
attribution placement (kept), stake/unstake valuation gating (excluded
from lp_pool_value), StrikeExposure parent id (already documented),
predict_account raw-ID read lookups (accepted).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
0xaslan and others added 10 commits July 2, 2026 16:47
The non-mechanical tail from the 2026-07-02 hygiene sweeps, promoted so
nothing evaporates: complete the public-read classify-or-delete pass
(H-4), the careful trade-flow dedup batch (H-5), the CadenceParams /
god-module maintainability backlog (H-6), and the pause-gate scope
decision for pool cash growth + lock_capital (G-1).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
H-4 — public-read classification completed:
- Pricer.expiry_market_id narrowed to public(package) (only in-package
  callers: the expiry_market binding assert and one test).
- The propbook raw_* read families classified as kept provenance/
  observability API via a group comment under each feed's Read
  Functions header, matching the README's documented raw/normalized
  read-pattern split. Future sweeps stop flagging them.

G-1 — pause/valuation gate exemptions decided and recorded in the
AGENTS.md settled list: top_up_live_expiry_cash growth is intentionally
pause-exempt (pause blocks risk at the mint gate; top-up backs existing
exposure and funds exits), and lock_capital needs no valuation gate
(only legal at supply==0, when ENotBootstrapped on both LP request
entrypoints means no queue entry or holder the lock protects exists).

Both removed from open-items; suites green (predict 363/363,
propbook 55/55).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three new families for classes no prior sweep covered:
- test-independence: unit-tests Rule 1 conformance — expected values
  independent of the implementation, no self-asserting snapshots, no
  measured-from-output tolerances (the LN_2 bug class).
- docs-drift: committed prose vs HEAD — every named identifier
  resolves, flows and vocabulary match current code.
- abort-code-multiplexing: one error code per distinct predicate
  (the EInvalidMarketTickSize precedent, done exhaustively).

Rule sweep is now 17 families; SKILL.md counts updated. Also formats
account_events.move (only prettier drift in the three packages).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All verified against source at HEAD 969dcf2. Post-rework prose drift,
doc-only (zero code change):

- Tick domain: u24 / "24-bit" / 2²⁴−1 → u30 / 30-bit / 2³⁰−1
  (constants::tick_bits!() = 30) across markets-and-positions,
  invariants, configuration, glossary.
- Removed cap/proof model still documented: drop
  EProofRequiredForLiveRedeem; live redeem requires account::Auth.
- Wrong identifiers: `redeem` → `redeem_live`; `drain_lp_requests` →
  `lp_book::drain`; event `PoolValued` → `FlushExecuted` (field
  pool_value); `profit_credits`/`profit_debits` →
  `profit_basis_credits`/`profit_basis_debits`; Registry.underlying_configs
  → MarketManager.underlying_configs.
- Missing admission_tick_size in set_template_cadence_config (prose +
  mermaid) and in the create_and_share_expiry_market snapshot list.
- account README: bare deposit/withdraw are stored-balance-only
  (self, coin)/(self, amount, ctx); document settle / deposit_funds /
  withdraw_funds as the accumulator-settling entrypoints.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
From the 17-family prove-clean sweep's polish trio.

abort-code-multiplexing — split the one genuinely-misleading name:
- pricing: the BS data-ABSENCE asserts (never-published spot/forward/svi)
  now abort EBlockScholesPriceUnavailable / EBlockScholesSVIUnavailable,
  distinct from the freshness asserts that keep EBlockScholesPriceStale /
  EBlockScholesSVIStale. The name previously lied when a feed had never
  published. Adds two absence expected_failure tests (skip the oracle
  seed). The remaining multi-site codes (EBalanceTooLow = absence vs
  below; EInsufficientCash = solvency-floor vs availability; the
  envelope/overflow clusters) are acceptable single-condition groupings —
  dispositioned, not split.

test-independence (unit-tests Rule 1) — expected values no longer built
from the production formula or a source fixed-point helper:
- strike_exposure_c1: survivor floor hard-coded to the independently
  computed 4_166 (derivation in a comment), deleting the helper that
  re-implemented the production split.
- backing_buffer / cash_backing: the gap buffer is expressed as gap / 4
  (λ_default = 0.25) using test constants, not math::mul(λ, gap); the
  math/config_constants helper + now-unused imports removed. The
  math::mul(λ, gap) == QUANTITY/4 assert stays as the independent check
  of the production helper itself.

predict 365/365.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The development-process state was split between the tracked predeploy/
directory and gitignored personal scratch (.claude/predict-design/), with
the connective artifacts (experiment tracker, decision journal) invisible
to teammates. This consolidates to one coherent, tracked system.

- predeploy/README.md becomes the system map: mission, authority order,
  surface table, lifecycle loops (finding->decision, experiment, audit,
  guard-change), and pickup entry points
- Promote the harness experiment tracker to predeploy/experiments.md:
  rewired to current IDs (C-*/RP-*), every experiment carries a driving
  ID and a pre-registered decision rule; adds E6 (RP-2 dust-window) and
  retires the genesis-CB probe (breaker removed in cc67ed9)
- Extract-and-delete the design-era journals (DECISION_JOURNAL, HISTORY):
  rejected-directions ledger + AUD-002 genesis-defaults promoted to
  AGENTS.md; D035 single-owner-facts event rule promoted to move.md;
  everything else verified superseded or already promoted
- Promote versioning-and-loaders.md (unimplemented proposal) to predeploy
- Add guard-removal duty-inventory + response-ladder rules to move.md;
  matching review obligations + checklist lines in code-review.md
- packages/predict/README.md gains the development-system front door;
  CLAUDE.md/AGENTS.md route to the map; predict-design/.redesign are
  declared personal-scratch-only

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xct5NpFmALuRtz2tQL18yG
…er wiring

The system's premise is that no session retains memory, so the artifacts
must machine-check each other. This adds the enforcement layer:

- predeploy/check.py: stdlib linter — every register pinning test exists
  as a real `fun` under tests/, RP-*/E*/item-ID cross-references resolve
  across the trackers, MEASURED risk claims link an existing findings doc,
  and named paths are live (historical/external-repo lines exempt).
  Mutation-tested both ways (injected fake test + dead path -> FATAL).
  First real run caught two drifts: a pre-extraction oracle path in the
  versioning proposal (annotated) and validated the keeper-runbook
  cross-repo reference handling.
- predict-audit wiring: check.py joins preflight in SKILL.md Step 1;
  register obligations added (re-verify every RP entry at HEAD, don't
  re-flag verified decisions, adversarially re-derive 1-2 entries per
  run); primer prior-awareness now covers response-policies.md and the
  AGENTS.md rejected-directions ledger, and states that entry-vs-HEAD
  drift is itself a finding.
- code-review.md: run check.py on diffs touching predeploy/, guards, or
  register-named tests; SKILL.md D004 citation re-pointed at the CLAUDE.md
  guardrail (caught by preflight's own D-id check after the journal
  extraction).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xct5NpFmALuRtz2tQL18yG
…int_payment

mint_prepared_exact_quantity and settle_mint_payment each derived the
builder-fee/subsidy/trader-fee split, so the max_cost slippage bound and the
actual withdrawal stayed equal only by hand-maintained sync. Move the max_cost
assert into settle_mint_payment, next to the withdraw_amount it bounds: one
derivation site, and the guard checks the exact total withdrawn by
construction. Behavior-preserving (suite 367/367; abort point unchanged within
the same atomic flow).

Adds a boundary pair pinning the all-in semantics: mint succeeds at
max_cost == net_premium + fee (505e6 for the at-the-money 1e9 fixture, exact
post-mint balance asserted) and aborts EMintCostAboveMax one unit below.
Both pass pre- and post-refactor. Removes H-2 from the predeploy tracker
(check.py clean).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Batch 7 split the never-published/non-normalizable BS read aborts into
EBlockScholesPriceUnavailable / EBlockScholesSVIUnavailable, distinct
from the freshness Stale codes. The concept docs and decisions.md only
named the Stale codes; integrators map abort codes, so the absence path
needs naming too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xct5NpFmALuRtz2tQL18yG
The full-PR multi-agent review found zero Critical/High and no correctness
or guard regressions; these are the confirmed doc-drift and system-
self-consistency findings, fixed in-branch because this PR is itself the
docs-drift-and-consistency sweep.

Doc drift (code contradicts the docs at HEAD):
- Three docs (liquidity-and-nav, architecture, glossary) claimed the LP
  drain refunds degenerate dust requests; lp_book::drain aborts
  EInvalidDrainMark (the exact claim risks.md was already corrected for) —
  reworded to the current abort behavior, C-4 as the intended fix.
- invariants.md order-id bit total 184 -> 196 (missed by the u24->u30 fix).
- registry.move stale "insert-only bindings" comment -> "current
  (admin-replaceable)" after P-4.
- AGENTS.md event-parity note named PoolValued/SupplyRefunded/WithdrawRefunded
  as current-but-unhandled; PoolValued is now FlushExecuted and the refund
  events don't exist (unimplemented C-4) — corrected.
- versioning-and-loaders.md "Shipped today" described a nonexistent
  allowed_versions VecSet-mirror surface; corrected to the real
  ProtocolConfig.version_watermark model + a staleness note. Fixed a
  pre-rename create_expiry_market reference.
- unit-tests.md worked example cited the deleted assert_plp_price_in_bounds.
- harness runtime.ts dangling #lp-nav-zero-brick anchor / stale NAV==0
  semantics -> C-4 / RP-2.

Tooling self-consistency (the PR contradicted its own new rules):
- check.py pinning-tests check was block-driven, so a missing / mislabelled /
  un-backticked Pinning-tests field slipped past silently; rewritten
  entry-driven so every RP entry must link a test or say "not yet catalogued"
  (mutation-tested). RP-3's field corrected to disclose that its cited test
  reaches NAV==0 via an underwater market and does not exercise the
  sticky-exclusion clamp's own trigger.
- All four audit workflows' settled-source lists now include
  response-policies.md, so verify agents can return "settled" with an RP-id
  per the register obligation this PR added to SKILL.md/primer.md.

Deferred to open-items H-7 (test strengthenings, not blockers): the RP-3
clamp-trigger test, cadence public-read classification + coverage, the
pricing forward-absence pinning test, and one-sided boundary assertions.

Verification: sui move build --warnings-are-errors clean; 367/367 tests;
harness tsc 0; check.py + preflight clean; all four workflows parse.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xct5NpFmALuRtz2tQL18yG
@0xaslan 0xaslan merged commit ed1c054 into main Jul 3, 2026
5 checks passed
@0xaslan 0xaslan deleted the at/predict-audit-sweep branch July 3, 2026 01:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants