Commit graph

518 commits

Author SHA1 Message Date
openhands
1d6dd8c628 fix: address review feedback on evaluate.sh (#380)
- container_name(): derive separator from compose version (_COMPOSE_SEP),
  so v1 (underscores) and v2 (hyphens) both resolve the right container name
- Drop buggy grep fallback for JSON branch extraction; python3 path is
  sufficient and safe; grep cannot reliably target only head.ref in the
  nested Gitea response
- Validate KRAIKEN/STAKE/LIQUIDITY_MANAGER after sourcing contracts.env to
  catch renamed variables with a clear infra_error instead of a cryptic
  'unbound variable' abort
- wait_exited: handle Docker 'dead' state alongside 'exited' to fail fast
  instead of polling the full timeout
- Ponder /ready timeout is now infra_error (was a logged warning); scenarios
  must not run against a partially-indexed chain
- Avoid double git fetch: only fetch the specific branch if the earlier
  --prune fetch (fallback path) has not already retrieved all remote refs
- Use mktemp -u so git worktree add creates the directory itself, avoiding
  failures on older git versions that reject a pre-existing target path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 10:12:34 +00:00
openhands
43c8d79afd fix: Holdout evaluator: fresh containerised stack per run (#380)
Adds scripts/harb-evaluator/evaluate.sh which:
- Accepts a PR number, resolves the branch via Codeberg API or git remote scan
- Checks out that branch into an isolated git worktree
- Boots a fresh docker compose stack with a unique COMPOSE_PROJECT name
- Waits for anvil healthy, bootstrap complete, ponder healthy + indexed
- Sources contract addresses from tmp/containers/contracts.env (never hardcoded)
- Exports EVAL_* env vars and runs any *.sh scripts under scenarios/
- Always tears down the stack and removes the worktree on exit (pass or fail)
- Returns 0 (gate passed), 1 (gate failed), or 2 (infra error)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 09:04:33 +00:00
johba
703185ea48 Merge pull request 'fix: HomeViewOffensive.vue trust section uses "Open." as a standalone claim (#313)' (#378) from fix/issue-313 into master 2026-02-28 16:22:22 +01:00
openhands
5d26100b58 ci: retrigger after infra failure 2026-02-28 14:54:03 +00:00
openhands
0b76ea9ca9 fix: HomeViewOffensive.vue trust section uses "Open." as a standalone claim (#313)
Replace "Open Source." with "On-Chain." — the repo is private so "open
source" is a false claim per PRODUCT-TRUTH.md §Code/Open Source and
UX-DECISIONS.md §Don't Say. "On-Chain." is accurate and consistent with
the subtitle already present in the section.

Also remove duplicate garbled sentence in the Adaptive Trading card
("The optimizer evolves — new versions ship as the protocol matures."
was a copy-paste repeat of the preceding clause).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 14:44:15 +00:00
openhands
10f7f1ebc0 fix: \HomeViewOffensive.vue\ trust section uses "Open." as a standalone claim (#313)
Replace vague "Open." with "Open Source." in the trust section heading
to give the claim concrete meaning and match the Source Code link below.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 14:21:03 +00:00
johba
80eb5a356f Merge pull request 'fix: taxDue ref lacks null guard before bigint arithmetic (#329)' (#376) from fix/issue-329 into master 2026-02-28 15:15:04 +01:00
openhands
bcebbd47c9 fix: \taxDue\ ref lacks null guard before bigint arithmetic (#329)
Initialize taxDue as ref<bigint>(0n) instead of ref<bigint>() so the
type is always bigint, eliminating the undefined in the Ref type and
making the bigint addition at line 219 type-safe without a null guard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 13:51:04 +00:00
johba
cfe113b1a0 Merge pull request 'fix: {{ taxPaidGes }} and {{ profit }} render empty during async load (#330)' (#373) from fix/issue-330 into master 2026-02-28 14:42:31 +01:00
openhands
57903329bf fix: \{{ taxPaidGes }}\ and \{{ profit }}\ render empty during async load (#330)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 13:21:06 +00:00
johba
c6f25c98ab Merge pull request 'fix: No allowance set before token0.transfer in swap callback (#339)' (#370) from fix/issue-339 into master 2026-02-28 13:46:19 +01:00
openhands
0fbc666c97 fix: No allowance set before \token0.transfer\ in swap callback (#339)
Add an explanatory comment to uniswapV3SwapCallback clarifying that
address(this) is pre-funded by _replaySwap before pool.swap() is
called, so no inline mint is required (unlike uniswapV3MintCallback).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 12:14:20 +00:00
johba
936d6cd60a Merge pull request 'fix: kraiken-lib missing from ARCHITECTURE.md directory map (#342)' (#368) from fix/issue-342 into master 2026-02-28 13:05:28 +01:00
openhands
e07fbf55a0 ci: retrigger after infra failure 2026-02-28 11:34:13 +00:00
openhands
e8c6070846 fix: kraiken-lib missing from ARCHITECTURE.md directory map (#342) 2026-02-28 11:20:50 +00:00
johba
b41dbddafe Merge pull request 'fix: Dual package managers: both package-lock.json and yarn.lock tracked (#343)' (#366) from fix/issue-343 into master 2026-02-28 12:13:27 +01:00
openhands
ab68e0cb68 fix: Dual package managers: both package-lock.json and yarn.lock tracked (#343)
Remove kraiken-lib/yarn.lock (npm is the sole package manager per CI and
build scripts), add packageManager field to kraiken-lib/package.json to
make the intent explicit, and add a single-package-manager CI step that
fails the build if yarn.lock reappears in kraiken-lib/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 10:51:59 +00:00
johba
d9a38921b6 Merge pull request 'fix: Unmatched /docs/* subroutes silently render empty DocsView (#347)' (#364) from fix/issue-347 into master 2026-02-28 11:43:44 +01:00
openhands
ca1ad9467c fix: Unmatched /docs/* subroutes silently render empty DocsView (#347) 2026-02-28 10:12:10 +00:00
johba
7f0aca8377 Merge pull request 'fix: Structural duplication of swap ABIs and buyKrk() across LocalSwapWidget and CheatsView (#353)' (#360) from fix/issue-353 into master 2026-02-28 11:05:10 +01:00
openhands
e5a5486499 fix: Structural duplication of swap ABIs and buyKrk() across LocalSwapWidget and CheatsView (#353)
Extract shared Uniswap ABIs (WETH_ABI, SWAP_ROUTER_ABI, UNISWAP_FACTORY_ABI,
UNISWAP_POOL_ABI), utility functions (isRecord, coerceString, getErrorMessage,
ensureAddress), and the wrap→approve→exactInputSingle flow into a new composable
useSwapKrk(). Both LocalSwapWidget and CheatsView now delegate to this single
source of truth, so swap logic changes only need to be made in one place.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 09:32:02 +00:00
johba
59d8364ef3 Merge pull request 'fix: Backtesting #6: Baseline strategies (HODL, full-range, fixed-width) + reporting (#320)' (#358) from fix/issue-320 into master 2026-02-27 15:15:58 +01:00
openhands
af86ca1226 fix: address review feedback on BaselineStrategies and Reporter
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 13:43:49 +00:00
openhands
77f0fd82fd fix: Backtesting #6: Baseline strategies (HODL, full-range, fixed-width) + reporting (#320)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 13:08:53 +00:00
johba
33c5244e53 Merge pull request 'fix: Backtesting #5: Position tracking + P&L metrics (#319)' (#354) from fix/issue-319 into master 2026-02-27 13:35:08 +01:00
openhands
cf8e7ee6ee fix: address review feedback on PositionTracker and StrategyExecutor
- Fix fee attribution: distribute fees only to positions whose tick range
  contains the active tick at close time (in-range weight), not by raw
  liquidity. FLOOR is priced far below current tick and rarely earns fees;
  the old approach would over-credit it and corrupt capital-efficiency and
  net-P&L numbers. Fallback to raw-liquidity weighting with a WARN log
  when no position is in range.

- Warn on first-close skip: when _closePosition finds no open record
  (first recenter, before any tracking), log [TRACKER][WARN] instead of
  silently returning so the gap is visible in reports.

- Add tick range assertion: require() that the incoming close snapshot
  tick range matches the stored open record — a mismatch would mean IL
  is computed across different ranges (apples vs oranges).

- Fix finalBlock accuracy: logSummary now calls
  tracker.logFinalSummary(tracker.lastNotifiedBlock()) instead of
  lastRecenterBlock, so the summary reflects the actual last replay block
  rather than potentially hundreds of blocks early.

- Initialize lastRecenterBlock = block.number in StrategyExecutor
  constructor to defer the first recenter attempt by recenterInterval
  blocks and document the invariant.

- Extract shared FormatLib: _str(uint256) and _istr(int256) were
  copy-pasted in both PositionTracker and StrategyExecutor. Extracted to
  FormatLib.sol internal library; both contracts now use `using FormatLib`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 12:02:29 +00:00
openhands
cfcf750084 fix: Backtesting #5: Position tracking + P&L metrics (#319)
- Add PositionTracker.sol: tracks position lifecycle (open/close per
  recenter), records tick ranges, liquidity, entry/exit blocks/timestamps,
  token amounts (via LiquidityAmounts math), fees (proportional to
  liquidity share), IL (LP exit value − HODL value at exit price), and
  net P&L per position. Aggregates total fees, cumulative IL, net P&L,
  rebalance count, Anchor time-in-range, and capital efficiency accumulators.
  Logs with [TRACKER][TYPE] prefix; emits cumulative P&L every 500 blocks.

- Modify StrategyExecutor.sol: add IUniswapV3Pool + token0isWeth to
  constructor (creates PositionTracker internally), call
  tracker.notifyBlock() on every block for time-in-range, and call
  tracker.recordRecenter() on each successful recenter. logSummary()
  now delegates to tracker.logFinalSummary().

- Modify BacktestRunner.s.sol: pass sp.pool and token0isWeth to
  StrategyExecutor constructor; log tracker address.

- forge fmt: reformat all backtesting scripts and affected src/test files
  to project style (number_underscore=thousands, multiline_func_header=all).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:23:18 +00:00
johba
a491ecb7d9 Merge pull request 'fix: Get KRK: inline swap widget for local dev, Uniswap link for production (#136)' (#338) from fix/issue-136 into master 2026-02-27 12:03:02 +01:00
openhands
f80565499e ci: retrigger after infra failure 2026-02-27 10:41:46 +00:00
openhands
cf4e401d03 fix: address review feedback on LocalSwapWidget and CheatsView
- LocalSwapWidget: move useWallet() to top-level <script setup> (was
  incorrectly called inside async buyKrk() event handler)
- LocalSwapWidget + CheatsView: fix misleading toast — all transactions
  are fully confirmed at that point, so say 'Swap complete' not 'Swap
  submitted'
- LocalSwapWidget: add $KRK sigil to warning/hint text for consistency
  with GetKrkView
- LocalSwapWidget: add comment on amountOutMinimum: 0n explaining it is
  intentional for a no-MEV local anvil environment
- CheatsView: apply same useWallet() fix (pre-existing anti-pattern)
- docs/ENVIRONMENT.md: document VITE_ENABLE_LOCAL_SWAP and related
  VITE_ variables in a new webapp env-var table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 10:32:04 +00:00
openhands
1b647f844a ci: fix clone auth — move netrc creds from environment to settings
woodpeckerci/plugin-git reads credentials via PLUGIN_NETRC_* env vars
(set from settings:), not CI_NETRC_* (set from environment:). The
previous fix in 57deaaa put the secret under environment:, so the
plugin never populated .netrc and git fell back to prompting, which
fails with GIT_TERMINAL_PROMPT=0.

Fix both ci.yml and e2e.yml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 09:41:51 +00:00
openhands
aef608b656 ci: retrigger after infra failure 2026-02-27 09:30:40 +00:00
johba
19df05843d Merge pull request 'fix: Backtesting #4: Deploy KrAIken contracts + recenter execution loop (#318)' (#349) from fix/issue-318 into master 2026-02-27 10:26:12 +01:00
johba
1f019ddacc Merge pull request 'fix: uint256ToBytesLittleEndian silently truncates above 2³²−1 (#294)' (#337) from fix/issue-294 into master 2026-02-27 10:20:02 +01:00
openhands
84203294af fix: Backtesting #4: Deploy KrAIken contracts + recenter execution loop (#318)
- Add BacktestKraiken.sol: extends MockToken with Kraiken-compatible interface
  (dual mint overloads — public mint(address,uint256) for EventReplayer and
  restricted mint(uint256) for LiquidityManager; peripheryContracts() stubs
  staking pool as address(0))

- Add KrAIkenDeployer.sol: library deploying OptimizerV3Push3 + LiquidityManager
  on the shadow pool, wiring BacktestKraiken permissions, setting fee destination,
  and funding LM with configurable initial mock-WETH capital (default 10 ETH)

- Add StrategyExecutor.sol: time-based recenter trigger (configurable block
  interval, default 100 blocks); logs block, pre/post positions (Floor/Anchor/
  Discovery tick ranges + liquidity), fees collected, and revert reason on skip;
  negligible-impact assumption documented as TODO(#319)

- Modify EventReplayer.sol: add overloaded replay() accepting an optional
  StrategyExecutor hook; maybeRecenter() called after each block advancement
  without halting replay on failure

- Modify BacktestRunner.s.sol: replace tokenA/B with MockWETH + BacktestKraiken,
  integrate KrAIkenDeployer + StrategyExecutor into broadcast block; configurable
  via RECENTER_INTERVAL and INITIAL_CAPITAL_WETH env vars; executor.logSummary()
  printed after replay

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 09:00:22 +00:00
johba
2ffdd55b4c Merge pull request 'fix: Backtesting #3: Replay historical Swap/Mint/Burn events against shadow pool (#317)' (#334) from fix/issue-317 into master 2026-02-27 09:40:03 +01:00
johba
b8e48a3d33 Merge pull request 'fix: Landing cleanup: 404 route, German comments, dead code, orphaned heading (#306)' (#346) from fix/issue-306 into master 2026-02-27 09:26:19 +01:00
openhands
17b100ef2a fix: address AI review feedback (round 2) for #317 event replay
- Guard final drift sample with `idx % LOG_INTERVAL != 0` to prevent
  double-counting stats when totalReplayed is an exact multiple of
  LOG_INTERVAL (the loop's _logCheckpoint already fired for that state)
- Hoist pool.slot0() before the guard and pass finalSqrtPrice/finalTick
  to _logSummary(), eliminating the redundant slot0 read inside it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 07:55:53 +00:00
openhands
1e6f817cf4 fix: Landing cleanup: 404 route, German comments, dead code, orphaned heading (#306)
- Add /:pathMatch(.*)*  catch-all route that redirects to / so unknown
  URLs no longer render blank
- Replace German inline comments in scrollBehavior with English equivalents
- Remove seven dead `// group: "navbar"` comments from /docs route and its
  child routes (the live group: 'navbar' property on the parent is kept)
- HomeView.vue and HomeViewMixed.vue already carry the renamed
  "Verified On-Chain" heading with supporting copy; no changes needed there

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 07:53:42 +00:00
openhands
ac32a1849c ci: retrigger after infra failure 2026-02-27 07:30:34 +00:00
johba
8c336ae0f5 Merge pull request 'fix: Stake.sol: exitPosition guard order (owner check before existence) (#307)' (#336) from fix/issue-307 into master 2026-02-27 08:14:09 +01:00
openhands
cd065275be fix: address AI review feedback for #317 event replay
- Cache pool.tickSpacing() as immutable in EventReplayer constructor
  to avoid a repeated external call per _replayMint() invocation
- Rename driftCount → driftCheckpoints for consistency with log label
- Add sqrtDriftBps to the per-checkpoint progress log line, using the
  now-live lastExpectedSqrtPrice field (previously written but never read)
- Guard _replaySwap(): skip and count events where amountSpecified ≤ 0,
  which would silently flip exact-input into exact-output mode
- Add a final drift sample after the while-loop for trailing events not
  covered by the last LOG_INTERVAL checkpoint
- Move EventReplayer construction outside the broadcast block in
  BacktestRunner (it uses vm.* cheat codes incompatible with real RPC)
- Change second vm.closeFile() from try/catch to a direct call so errors
  surface rather than being silently swallowed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 07:09:29 +00:00
openhands
bce4059de9 fix: Get KRK: inline swap widget for local dev, Uniswap link for production (#136)
- Add `VITE_ENABLE_LOCAL_SWAP` env var to config.ts (defaults false)
- Create LocalSwapWidget.vue: inline ETH→KRK swap (wrap→approve→exactInputSingle)
- GetKrkView.vue: show LocalSwapWidget when VITE_ENABLE_LOCAL_SWAP=true, Uniswap link otherwise
- docker-compose.yml: set VITE_ENABLE_LOCAL_SWAP=true for webapp service

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 06:55:41 +00:00
openhands
49d7d708d1 fix: uint256ToBytesLittleEndian silently truncates above 2³²−1 (#294) 2026-02-27 06:43:08 +00:00
openhands
6eacfe1975 fix: \uint256ToBytesLittleEndian\ silently truncates above 2³²−1 (#294)
Expand the output buffer from 4 bytes to 32 bytes and iterate all 32
positions, so values ≥ 2³² are encoded correctly instead of silently
dropped. Update tests to assert 32-byte output and add coverage for
2³², 2¹²⁸, and max uint256 roundtrips.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 06:42:59 +00:00
openhands
24fdcd3dcd fix: Stake.sol: exitPosition guard order (owner check before existence) (#307)
Check pos.creationTime == 0 before pos.owner != msg.sender so that
calling exitPosition on a non-existent position correctly reverts with
PositionNotFound instead of the misleading NoPermission(caller, 0x0).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 06:33:32 +00:00
openhands
a884f8a5c9 ci: retrigger after infra failure 2026-02-27 06:27:58 +00:00
johba
9341673a1a Merge pull request 'fix: Ponder: fix mintNextHourProjected divisor, dead param, dead code (#308)' (#333) from fix/issue-308 into master 2026-02-27 07:20:02 +01:00
openhands
a3eb406e46 fix: Backtesting #3: Replay historical Swap/Mint/Burn events against shadow pool (#317)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 06:17:54 +00:00
openhands
896fffb2e8 fix: Backtesting #3: Replay historical Swap/Mint/Burn events against shadow pool (#317)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 06:12:03 +00:00