Fixes#618
## Changes
Add stack depth validation in processExecIf() so asymmetric EXEC.IF branches (where one branch pushes more values than the other) throw an explicit error instead of silently padding with '0'. Error messages identify both branch depths for DYADIC and BOOLEAN stacks. Removed dead-code '0'/'false' fallbacks in buildAssignments and reconstruction. Updated existing unbalanced-branch tests to expect errors; added regression tests for error message content and BOOLEAN mismatch. All existing seed files (optimizer_v3.push3, optimizer_seed.push3) continue to transpile.
Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/1033
Reviewed-by: Disinto_bot <disinto_bot@noreply.codeberg.org>
Add TypeScript unit test suite for the Push3 transpiler using Node's
built-in test runner (node:test) with tsx. 47 tests across 12 suites
covering parser, stack underflow/overflow, EXEC.IF balanced/unbalanced/
nested branching, arithmetic, boolean ops, name binding, and integration.
Update CI to run `npm test` (which now includes unit tests + existing
bash tests) and scope transpiler-tests step to only trigger on changes
to tools/push3-transpiler/**.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move overflow guard to the actual vulnerable site:
ThreePositionStrategy._computeFloorTickWithSignal() line 262 where
vwapX96 >> 32 is cast to int128 for _tickAtPriceRatio. Values
exceeding int128.max now skip mirror tick (fallback to scarcity/clamp)
instead of reverting.
Remove incorrect require from Optimizer._buildInputs() which guarded
a non-existent int256 cast path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add address(0) guard to fee transfer condition in _scrapePositions so
that when feeDestination is uninitialized, fees accrue as deployable
liquidity instead of reverting on safeTransfer to the zero address.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wrap mint_lp and burn_lp ops in _executeOp with try/catch to match
the soft-fail pattern used by buy, sell, stake, and unstake. Replace
burn_lp's require() with a soft return for out-of-range index validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add max-iterations guard (60 polls × 5s = 5 min) to both cooldown
polling loops with explicit error on timeout
- Use LAST_RECENTER (already validated) as fallback instead of "0" for
post-seed-buy lastRecenterTime read, preventing silent cooldown skip
on transient RPC failure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix positions() ABI selector: uint256 -> uint8 (Stage enum)
- Replace fixed sleeps with polling loops checking on-chain timestamps
- Add trailing period to 'amplitude not reached.' error hint
- Remove 'was never set' feeDestination scenario (always set by deploy)
- Clarify warning comment scope in bootstrap-common.sh
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
batch-eval.sh mutates OptimizerV3.sol by injecting Push3 candidates but
never restores it on exit. Add a backup/restore trap so the file is
always returned to its committed state, and add a CI step that fails
loudly if OptimizerV3.sol is left dirty after any pipeline step.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add recovery procedure documentation and automated recovery script for
when the VWAP bootstrap fails partway through (e.g. second recenter
reverts due to insufficient price movement).
- Add "Recovery from failed mid-sequence bootstrap" section to
docs/mainnet-bootstrap.md with diagnosis steps and manual recovery
- Create scripts/recover-bootstrap.sh to automate diagnosis and retry
- Add warning comments in BootstrapVWAPPhase2.s.sol, DeployBase.sol,
and bootstrap-common.sh referencing the recovery procedure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Missed reference — deploy-optimizer.sh still called npx ts-node,
which would fail now that ts-node is removed from devDependencies.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract bear-mode default values (0, 3e17, 100, 3e17) into file-level
constants in IOptimizer.sol so both Optimizer._bearDefaults() and
LiquidityManager.recenter()'s catch block reference a single source of
truth instead of independent hardcoded literals.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The @return annotations were orphaned after _buildInputs() was inserted
between the NatSpec block and getLiquidityParams(). Move them to directly
precede getLiquidityParams() where they belong.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The pure override in OptimizerInputCapture could not write to storage,
and getLiquidityParams calls calculateParams via staticcall which
prevents both storage writes and event emissions.
Fix: extract the input-building normalization from getLiquidityParams
into _buildInputs() (internal view, behavior-preserving refactor).
The test harness now exposes _buildInputs() via getComputedInputs(),
allowing tests to assert actual normalized slot values.
Updated tests for pricePosition, timeSinceRecenter, volatility,
momentum, and utilizationRate to assert non-zero captured values.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a Push3 Seed Pool section to docs/ARCHITECTURE.md documenting all
manifest.jsonl fields (file, origin, date, fitness, fitness_flags, run,
generation, note) with type, required/optional status, and allowed values.
References the machine-readable manifest.schema.json for validation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Address review feedback:
- Remove candidate input (Push3 transpilation not wired; documented in
notes.candidate_injection as planned follow-up)
- Mark run-attack-suite step as status="planned" with run_attack_suite_gap note
- Update execution.invocation to only pass env vars red-team.sh actually reads
- Fix export-vectors args to include --eth-extracted and --eth-before flags
- Clarify export-vectors only runs when floor_broken (BROKE=true)
- Document tmp/red-team-snapshots.jsonl (AttackRunner replay side output)
- Add comment that {attack_type} in products.attack_vectors.path is
runtime-computed by promote-attacks.sh, not a formula input
- Fix schema comment notation (§ → ##)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add formulas/run-user-test.toml — a sense-only process definition for
persona-based UX evaluation. Defines 5 personas across 2 funnels
(passive-holder: tyler/alex/sarah; staker: priya/marcus), full stack
lifecycle (start → run → collect → stop → deliver), and the three
standard evidence delivery products (evidence JSON committed to main,
screenshots referenced in evidence, summary as issue comment).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add evidence/ with subdirs for evolution, red-team, holdout, and user-test.
Each subdir has a .gitkeep and README.md documents the JSON schema for all four
process types so formulas and the planner have a canonical contract to read/write.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- cleanup_worktree: add `git branch -D $BRANCH` to prevent stale local
branch refs accumulating on push failure (bug fix)
- .netrc parser: replace fragile line-count awk with field-iteration
approach that handles both multi-line and single-line .netrc formats
- ETH formatting: pass values as argv to python3 instead of interpolating
into the code string, removing the injection surface
- mktemp -u: generate path without pre-creating directory; git worktree
add creates it, avoiding the "already exists" error on some git versions
- mkdir -p guard before cp to attacks destination directory
- sed portability: `s/-\+/-/g` → `s/--*/-/g` (POSIX-compliant)
- red-team.sh: capture PIPESTATUS[0] from promote-attacks pipe and emit
a distinct warning log line when promotion fails
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add scripts/harb-evaluator/promote-attacks.sh which:
- Reads tmp/red-team-attacks.jsonl after a successful red-team run
- Deduplicates by op-type fingerprint against all existing attack files
- Classifies attack type (staking, il-crystallization, fee-drain-oscillation,
floor-ratchet, lp-manipulation, floor-attack) from the op sequence
- Creates an isolated git worktree branch from origin/master
- Commits the attack file to onchain/script/backtesting/attacks/<type>-<candidate>.jsonl
- Opens a Codeberg PR with attack type, ETH extracted, and optimizer profile
Integrate into red-team.sh: when the floor breaks (ETH extracted) and an
attack export exists, promote-attacks.sh is called automatically (non-fatal).
Gracefully no-ops when CODEBERG_TOKEN / ~/.netrc are absent.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
These directories contain TOML process definitions and JSON evidence
files — no code changes that need testing. Also excludes docs/ and
*.md from the main CI pipeline (e2e already excluded these).
Prepares for formula and evidence PRs landing without triggering
unnecessary CI runs.
## Summary
Bundled dust cleanup for `push3-evolution/evolve.sh` subsystem:
- **#716**: Fix null-fitness crash in generation JSONL parsing — `int(d.get('fitness', 0))` → `int(d.get('fitness') or 0)` (avoids `TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'` when fitness is JSON `null`)
- **#944**: Add `processExecIf_fix` to `ZERO_RATED_FLAGS` so inflated scores from that flag are zero-rated during pool admission/eviction
- **#945**: `fitness_flags` is comma-separated in practice — update `manifest.schema.json` description from 'Space-separated' to 'Comma-separated' and use `flags.split(',')` in `effective_fitness` instead of substring match
- Fix pre-existing SC2086: quote `$i` in `printf` argument (ShellCheck)
## Test plan
- [ ] ShellCheck passes on `tools/push3-evolution/evolve.sh`
- [ ] CI passes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/987
Reviewed-by: Disinto_bot <disinto_bot@noreply.codeberg.org>