Commit graph

810 commits

Author SHA1 Message Date
openhands
729191d8ca ci: retrigger after infra failure 2026-03-14 02:32:22 +00:00
openhands
cbab4c36da fix: NPM_ADDR may be Base Sepolia address in both files (#686)
Replace 0x27F971cb582BF9E50F397e4d29a5C7A34f11faA2 (Base Sepolia
NonfungiblePositionManager) with the correct Base mainnet address
0x03a520B32c04bf3beef7BEb72E919cF822Ed34F3 in all four files that
referenced it, and add an inline comment citing the chain and source.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 02:22:51 +00:00
johba
93e3495252 Merge pull request 'fix: Other clamped params lack named constants (#703)' (#725) from fix/issue-703 into master 2026-03-14 03:07:43 +01:00
openhands
f3ddec9427 fix: Other clamped params lack named constants (#703)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 01:40:41 +00:00
johba
051d236eb2 Merge pull request 'fix: evo_run004_champion fitness inflated by token value (#670) (#704)' (#722) from fix/issue-704 into master 2026-03-14 02:28:07 +01:00
openhands
c42a1ca768 fix: evo_run004_champion fitness inflated by token value (#670) (#704)
- Add fitness_flags="token_value_inflation" to evo_run004_champion in
  manifest.jsonl so callers can detect the inflated value without
  discarding the entry entirely.
- Add effective_fitness() helper in evolve.sh pool admission (step 5)
  that returns 0 for any entry with a token_value_inflation flag,
  preventing inflated scores from biasing the top-100 evolved pool
  ranking or eviction decisions.
- Document in evolve.sh that raw fitness values are only comparable
  within the same evaluation run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 01:08:13 +00:00
johba
d0eae8b261 Merge pull request 'fix: Issue template (push3-seed.yaml) doesn't enumerate manifest.jsonl fields (#705)' (#717) from fix/issue-705 into master 2026-03-14 01:57:24 +01:00
openhands
038c9ca7bc fix: Issue template (push3-seed.yaml) doesn't enumerate manifest.jsonl fields (#705) 2026-03-14 00:37:06 +00:00
openhands
6d23073e2f fix: Issue template (push3-seed.yaml) doesn't enumerate manifest.jsonl fields (#705) 2026-03-14 00:17:04 +00:00
johba
c5a7941259 Merge pull request 'fix: int(e.get('fitness', 0)) crashes on null-fitness manifest entries (#711)' (#715) from fix/issue-711 into master 2026-03-14 01:07:07 +01:00
openhands
b7d0b63ca1 fix: int(e.get('fitness', 0)) crashes on null-fitness manifest entries (#711) 2026-03-13 23:37:00 +00:00
johba
860b56f216 Merge pull request 'fix: evo_run004_champion fitness note references unresolved issue #670 (#685)' (#702) from fix/issue-685 into master
Reviewed-on: https://codeberg.org/johba/harb/pulls/702
Reviewed-by: review_bot <review_bot@noreply.codeberg.org>
2026-03-13 21:46:27 +01:00
openhands
23ca929f8a ci: retrigger after infra failure 2026-03-13 20:43:28 +00:00
johba
0c4cd23dfa fix: feat: Seed kindergarten — persistent top-100 candidate pool (#667) (#683)
Fixes #667

## Changes
## Summary

Implemented persistent top-100 candidate pool in `tools/push3-evolution/evolve.sh`:

### Changes

**`--run-id <N>` flag** (line 96)
- Optional integer; auto-increments from highest `run` field in `manifest.jsonl` when omitted
- Zero-padded to 3 digits (`001`, `002`, …)

**Seeds pool constants** (after path canonicalization)
- `SEEDS_DIR` → `$SCRIPT_DIR/seeds/`
- `POOL_MANIFEST` → `seeds/manifest.jsonl`
- `ADMISSION_THRESHOLD` → `6000000000000000000000` (6e21 wei)

**`--diverse-seeds` mode** now has two paths:
1. **Pool mode** (pool non-empty): random-shuffles the pool and takes up to `POPULATION` candidates — real evolved diversity, not parametric clones
2. **Fallback** (pool empty): original `seed-gen-cli` parametric variant behavior
- Both paths fall back to mutating `--seed` to fill any shortfall

**Step 5 — End-of-run admission** (after the diff step):
1. Scans all `generation_*.jsonl` in `OUTPUT_DIR` for candidates with `fitness ≥ 6e21`
2. Maps `candidate_id` (e.g. `gen2_c005`) back to `.push3` files in `WORK_DIR` (still exists since cleanup fires on EXIT)
3. Deduplicates by SHA-256 content hash against existing pool
4. Names new files `run{RUN_ID}_gen{N}_c{MMM}.push3`
5. Merges with existing pool, sorts by fitness descending, keeps top 100
6. Copies admitted files to `seeds/`, removes evicted evolved files (never hand-written), rewrites `manifest.jsonl`

Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/683
Reviewed-by: review_bot <review_bot@noreply.codeberg.org>
2026-03-13 20:45:03 +01:00
johba
944e537d5b Merge pull request 'fix: LiquidityManager silently clamps anchorWidth to 100, undocumented upper bound (#689)' (#701) from fix/issue-689 into master 2026-03-13 20:36:03 +01:00
johba
e230a62e11 fix: feat: LLM seed — Fee Maximizer optimizer (#673) (#696)
Fixes #673

## Changes
Done. Here's a summary of what was implemented:

## Changes

**`tools/push3-evolution/seeds/llm_fee_maximizer.push3`** (new file)
A Push3 optimizer seed implementing the "every trade pays us" philosophy. It reads `percentageStaked` (slot 0) and `averageTaxRate` (slot 1), then branches on two thresholds:
- Staking threshold: 60% (bullish vs. neutral sentiment)
- Tax threshold: 10% of 1e18 (high vs. low swap volume)

Strategy matrix:
| | tax < 10% | tax ≥ 10% |
|---|---|---|
| **staked < 60%** | AS=0.70, AW=60, DD=0.50 | AS=0.80, AW=80, DD=0.60 |
| **staked ≥ 60%** | AS=0.90, AW=40, DD=0.80 | AS=0.95, AW=50, DD=0.90 |

CI is always 0. Anchor share is always ≥ 0.70e18 (capital stays in fee-earning zone). High staking shifts discovery depth up; high tax widens the anchor to capture more swap volume.

**`tools/push3-evolution/seeds/manifest.jsonl`** — new entry for `llm_fee_maximizer.push3` with `origin=llm`.

Transpiled successfully: 48-line Solidity function body, outputs correctly bound to `ci`, `anchorShare`, `anchorWidth`, `discoveryDepth`.

Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/696
Reviewed-by: review_bot <review_bot@noreply.codeberg.org>
2026-03-13 19:56:39 +01:00
johba
382b7ec9b3 Merge pull request 'fix: feat: LLM seed — Momentum Follower optimizer (#674)' (#695) from fix/issue-674 into master 2026-03-13 19:39:50 +01:00
openhands
39c25fa330 fix: LiquidityManager silently clamps anchorWidth to 100, undocumented upper bound (#689)
- Extract magic number into named constant MAX_ANCHOR_WIDTH = 100 in LiquidityManager.sol
- Document effective ceiling in IOptimizer.sol natspec for anchorWidth return value
- Add testAnchorWidthAbove100IsClamped in LiquidityManager.t.sol asserting that
  optimizer-returned anchorWidth=150 is silently clamped to 100 (not rejected)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 18:14:37 +00:00
openhands
04dc44e76b ci: retrigger 2026-03-13 18:12:49 +00:00
openhands
f59361b047 state: LLM seed — Momentum Follower optimizer (#695) 2026-03-13 15:12:05 +00:00
openhands
24c4e94a6b fix: feat: LLM seed — Momentum Follower optimizer (#674)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 14:50:26 +00:00
johba
e484d4b03a feat: issue templates — bug, feature, push3-seed, refactor (#678)
Four templates for Codeberg issue creation:

- **Bug** — what, repro steps, affected files, acceptance criteria
- **Feature** — problem, solution, affected files (incl e2e tests), max 5 acceptance criteria
- **Push3 Seed** — strategy philosophy, behavior spec, pre-filled reference files + register mapping
- **Refactor** — what, approach, affected files, risks

All templates require affected files and acceptance criteria — the two things the dev-agent needs most. Push3 seed template has pre-filled deps (#667) and reference docs.

Gardener agent can enforce these on unstructured issues that come in without templates.

Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/678
Reviewed-by: review_bot <review_bot@noreply.codeberg.org>
2026-03-13 13:02:50 +01:00
johba
3226aa58b6 Merge pull request 'feat: seed kindergarten — initial population with OG + first evolution champion' (#681) from chore/seed-kindergarten-initial into master
Reviewed-on: https://codeberg.org/johba/harb/pulls/681
2026-03-13 11:51:30 +01:00
johba
68c0769b5f Merge pull request 'fix: Stale JSDoc in navigateToStakePage refers to '/stake' not '/app/stake' (#509)' (#682) from fix/issue-509 into master
Reviewed-on: https://codeberg.org/johba/harb/pulls/682
2026-03-13 11:49:21 +01:00
johba
f22fe22f80 feat: STATE.md — running log of what harb is and does (#680)
Seeded with current reality. Dev-agent appends one line per merge (before merge, on the PR branch — goes through review). Planner will collapse into compact snapshot periodically.

Ref: dark-factory#5
Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/680
2026-03-13 11:46:34 +01:00
openhands
a18512a644 fix: Stale JSDoc in navigateToStakePage refers to '/stake' not '/app/stake' (#509) 2026-03-13 10:37:14 +00:00
openhands
c7196aa2b0 feat: seed kindergarten — initial population with OG + first evolution champion
seeds/optimizer_v3.push3     — hand-written original (8.26e21)
seeds/evo_run004_champion.push3 — first evolution winner (2.31e24, gen 3)
seeds/manifest.jsonl         — fitness + provenance tracking

Note: champion fitness inflated by token value (#670). Strategy is
'always bull' — wide positions, max anchor share. Pending ETH-only
metric fix to validate.
2026-03-13 10:32:35 +00:00
johba
f1b64a448f Merge pull request 'fix: claude subprocess not killed on INT/TERM in cleanup trap (#530)' (#679) from fix/issue-530 into master 2026-03-13 11:26:02 +01:00
openhands
659044e2d1 fix: claude subprocess not killed on INT/TERM in cleanup trap (#530)
Track CLAUDE_PID before launching the claude subprocess so cleanup()
can kill it before reverting Anvil state. Running claude via `&` +
`wait` lets the trap fire immediately on INT/TERM, killing the
subprocess and preventing it from making calls against an
already-reverted chain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 09:48:34 +00:00
johba
8b1d1ce146 Merge pull request 'fix: fix: Fitness metric should measure ETH only, not token value (#670)' (#677) from fix/issue-670 into master 2026-03-13 10:39:17 +01:00
openhands
defa1bfb6c fix: fix: Fitness metric should measure ETH only, not token value (#670)
Replace _positionEthValue() with _positionEthOnly() in FitnessEvaluator.t.sol.
The new function returns only the WETH component of each position (amount0 if
token0isWeth, else amount1), ignoring KRK token value entirely. This prevents
evolution from gaming the fitness metric by inflating KRK price through position
placement — the score now reflects actual ETH reserves only.

Also removes the now-unused FullMath import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 09:11:31 +00:00
johba
3f435f8459 fix: evolution scoring — 3 bugs made all candidates report fitness=0 (#665)
## Three bugs in evolve.sh

1. **Heredoc stdin conflict** — `py_stats()` used `<<PYEOF` heredoc which stole stdin from the pipe, so python never received score values → stats always `min=0 max=0 mean=0`

2. **Bash integer overflow** — global best comparison used `[ $MAX -gt $GLOBAL_BEST_FITNESS ]` which overflows on uint256 wei values (>9.2e18) → best always tracked as 0

3. **candidate_id mismatch** — evolve.sh looked up `gen0_c000` but batch-eval produces `candidate_000` (derived from filename) → score lookup always returned default 0

All 3 previous evolution runs (150+ candidates) reported all zeros despite batch-eval correctly scoring them at ~8.26e21 wei.

## Fix
- `py_stats`: heredoc → `python3 -c` inline
- Global best: bash `[ -gt ]` → `python3` big number comparison
- Score lookup: use `basename $CAND_FILE` instead of synthetic CID

Co-authored-by: root <root@debian-g-2vcpu-8gb-ams3-01>
Reviewed-on: https://codeberg.org/johba/harb/pulls/665
Reviewed-by: review_bot <review_bot@noreply.codeberg.org>
2026-03-13 10:02:24 +01:00
johba
5127e96ab3 Merge pull request 'fix: $FLOOR_BEFORE/$FLOOR_AFTER unquoted inside python3 -c string (#531)' (#666) from fix/issue-531 into master 2026-03-13 09:57:01 +01:00
openhands
2ae07e7a49 fix: $FLOOR_BEFORE/$FLOOR_AFTER unquoted inside python3 -c string (#531) 2026-03-13 08:28:26 +00:00
johba
b6301b2c96 Merge pull request 'fix: Protocol Mechanics section in agent prompt still exposes ethPerToken formula (#550)' (#662) from fix/issue-550 into master 2026-03-13 09:16:47 +01:00
openhands
6924cb03f3 fix: Protocol Mechanics section in agent prompt still exposes ethPerToken formula (#550) 2026-03-13 07:47:35 +00:00
johba
bdea40f314 Merge pull request 'fix: No formal IOptimizer interface for getLiquidityParams ABI (#556)' (#660) from fix/issue-556 into master 2026-03-13 08:45:21 +01:00
openhands
d01c561028 fix: No formal IOptimizer interface for getLiquidityParams ABI (#556)
Add IOptimizer interface with getLiquidityParams() signature to IOptimizer.sol
so upgrade-compatibility is explicit and static analysis can catch ABI mismatches.
Update LiquidityManager to hold optimizer as IOptimizer instead of concrete Optimizer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 07:20:42 +00:00
johba
fa561ce78e Merge pull request 'fix: ARCHITECTURE.md missing tools/ directory entry (#561)' (#658) from fix/issue-561 into master 2026-03-13 08:14:40 +01:00
johba
8064623a54 fix: feat: Push3 input redesign — normalized indicators instead of raw protocol values (#635) (#649)
Fixes #635

## Changes
The implementation is complete and committed. All 211 tests pass.

## Summary of changes

### `onchain/src/Optimizer.sol`
- **Replaced raw slot inputs** with normalized indicators in `getLiquidityParams()`:
  - Slot 2 `pricePosition`: where current price sits within VWAP ± 11 000 ticks (0 = lower bound, 0.5e18 = at VWAP, 1e18 = upper bound)
  - Slot 3 `volatility`: `|shortTwap − longTwap| / 1000 ticks`, capped at 1e18
  - Slot 4 `momentum`: 0 = falling, 0.5e18 = flat, 1e18 = rising (5-min vs 30-min TWAP delta)
  - Slot 5 `timeSinceRecenter`: `elapsed / 86400s`, capped at 1e18
  - Slot 6 `utilizationRate`: 1e18 if current tick is within anchor position range, else 0
- **Extended `setDataSources()`** to accept `liquidityManager` + `token0isWeth` (needed for correct tick direction in momentum/utilizationRate)
- **Added `_vwapToTick()`** helper: converts `vwapX96 = price × 2⁹⁶` to tick via `sqrt(vwapX96) << 48`, with TickMath bounds clamping
- All slots gracefully default to 0 when data sources are unconfigured or TWAP history is insufficient (try/catch on `pool.observe()`)

### `onchain/src/OptimizerV3Push3.sol`
- Updated NatSpec to document the new `[0, 1e18]` slot semantics

### New tests (`onchain/test/`)
- `OptimizerNormalizedInputsTest`: 18 tests covering all new slots, token ordering, TWAP fallback, and a bounded fuzz test
- `mocks/MockPool.sol`: configurable `slot0()` + `observe()` with TWAP tick math
- `mocks/MockLiquidityManagerPositions.sol`: configurable anchor position bounds

Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/649
Reviewed-by: review_bot <review_bot@noreply.codeberg.org>
2026-03-13 07:53:46 +01:00
openhands
b5cf1ea600 fix: ARCHITECTURE.md missing tools/ directory entry (#561) 2026-03-13 06:37:02 +00:00
johba
5e72533b3e Merge pull request 'ci: skip e2e for tools-only and docs-only PRs' (#641) from ci/skip-e2e-for-tools into master
Reviewed-on: https://codeberg.org/johba/harb/pulls/641
Reviewed-by: review_bot <review_bot@noreply.codeberg.org>
2026-03-13 07:32:20 +01:00
johba
d3de7d410a Merge pull request 'fix: feat: Push3 evolution — crossover operator (#639)' (#657) from fix/issue-639 into master 2026-03-13 07:29:26 +01:00
openhands
f8b765a9f8 fix: feat: Push3 evolution — crossover operator (#639)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 05:54:48 +00:00
johba
709dfccf7e Merge pull request 'fix: feat: Push3 evolution — diverse seed population (#638)' (#656) from fix/issue-638 into master 2026-03-13 06:44:34 +01:00
openhands
89a2734bff fix: address review findings for diverse seed population (#638)
- evolve.sh: fix fail-in-subshell bug — run seed-gen-cli as a direct
  command so its exit code is checked by the parent shell and fail()
  aborts the script correctly; redirect stderr to log file instead of
  discarding it with 2>/dev/null
- seed-generator.ts: reorder enumerateVariants() to put
  STAKED_THRESHOLDS outermost (192 entries/block) so that
  selectVariants(6) with stride=192 covers all 6 staked% thresholds;
  remove false doc claim about "first variant is current seed config";
  add comments explaining CI=0n is intentional in all presets
- seed-gen-cli.ts: emit a stderr diagnostic when count exceeds the
  1152-variant cap so the cap is visible rather than silently producing
  fewer files than requested
- test: strengthen n=6 test to assert all STAKED_THRESHOLDS values are
  represented in the selected variants

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 05:21:05 +00:00
openhands
850131b74f fix: feat: Push3 evolution — diverse seed population (#638)
Add seed-generator.ts module and seed-gen-cli.ts CLI that produce
parametric Push3 variants for initial population seeding.

Variants systematically cover:
  - Staked% thresholds: 80, 85, 88, 91, 94, 97
  - Penalty thresholds: 30, 50, 70, 100
  - Bull params: 4 presets (aggressive → mild)
  - Bear params: 4 presets (standard → very mild)
  - Tax distributions: exponential (seed), linear, sqrt

Total combination space: 6×4×4×4×3 = 1152 variants.
selectVariants(n) samples evenly so every axis is represented.

evolve.sh gains --diverse-seeds flag: when set, gen_0 is seeded with
parametric variants instead of N copies of the same mutated seed.
Remaining slots (if population > generated variants) fall back to
mutations of the base seed.

All generated programs pass transpiler stack validation (33 new tests).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 04:48:04 +00:00
johba
b8a503c2df Merge pull request 'fix: feat: Push3 default outputs — crash/no-output falls back to bear strategy (#634)' (#651) from fix/issue-634 into master 2026-03-13 05:22:05 +01:00
openhands
c87064dc6c fix: feat: Push3 default outputs — crash/no-output falls back to bear strategy (#634)
Three defensive layers so every Push3 program runs without reverting:

Layer A (transpiler/index.ts): assign bear defaults (CI=0, AS=0.3e18,
AW=100, DD=0.3e18) to all four outputs at the top of calculateParams.
Any output the evolved program does not overwrite keeps the safe default.

Layer B (transpiler/transpiler.ts): graceful stack underflow — dpop/bpop
return '0'/'false' instead of throwing, and the final output-pop falls
back to bear-default literals when fewer than 4 values remain on the
stack. Wrong output count no longer aborts transpilation.

Layer C (transpiler/transpiler.ts + index.ts): wrap the entire function
body in `unchecked {}` so integer overflow wraps (matching Push3), and
emit `(b == 0 ? 0 : a / b)` for every DYADIC./ (div-by-zero → 0,
matching Push3 no-op semantics).

Layer 2 (Optimizer.sol getLiquidityParams): clamp the three fraction
outputs (capitalInefficiency, anchorShare, discoveryDepth) to [0, 1e18]
after abi.decode so a buggy evolved program cannot produce out-of-range
values even if it runs without reverting.

Regenerated OptimizerV3Push3.sol with the updated transpiler; all 193
tests pass (34 Optimizer/OptimizerV3Push3 tests explicitly).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 03:47:49 +00:00
johba
8e4bd905ac Merge pull request 'fix: fix: Bootstrap VWAP with seed trade during deployment (#567) (#567)' (#633) from fix/issue-567 into master 2026-03-13 03:17:30 +01:00