feat(v1.4): PreCompact hook + rebuild logic in augment mode (closes #139) - #177
Merged
Merged
Conversation
…elope Adds rebuild_v14() that calls the v1.3 retrieve() (L0+L1+L2.5) instead of the v1.2.0a0 per-token union workaround, threads session_id from turns.jsonl into per-turn records, and packs L0 -> session-scoped -> L2.5/L1 within a configurable token budget. emit_pre_compact_envelope() wraps blocks in the harness's hookSpecificOutput.additionalContext JSON shape. load_rebuilder_config() honors [rebuilder] turn_window_n and token_budget keys in .aelfrice.toml (defaults 50 / 4000). main() entry point added so the module can register as a Claude Code PreCompact hook directly. Legacy rebuild() and DEFAULT_TOKEN_BUDGET kept for backwards compat with the existing aelf rebuild CLI and eval harness.
Switches hook.pre_compact() to call rebuild_v14() and wrap the result in the harness's hookSpecificOutput.additionalContext JSON envelope. Resolves the [rebuilder] section of .aelfrice.toml from the payload's cwd and honors turn_window_n / token_budget overrides; both kwargs on pre_compact() default to None now and let the config win. Empty-transcript and missing-store edge cases short-circuit to exit 0 with no additionalContext written, per issue #139 acceptance. Existing test_hook_pre_compact assertions updated to parse the JSON envelope via a helper rather than grepping raw stdout. The no-turns-but-locked-beliefs case used to return the L0 frame; that behaviour now belongs to the SessionStart channel and the test is updated to assert silence.
_cmd_rebuild now calls rebuild_v14() (the same path the PreCompact hook drives) instead of the legacy v1.2.0a0 rebuild(). Defaults follow [rebuilder] in .aelfrice.toml when present; --n / --budget flags override. Help text updated. Drops the "[v1.1 rebuilder alpha]" suffix on the install message.
15 new deterministic tests covering issue #139 acceptance: - AC1 ordering: locked -> session_scoped -> retrieve() hits, both through the hook envelope and via the pure rebuild_v14() boundary. - AC2 edge cases: empty transcript, missing store, both via the pre_compact() hook and via the new context_rebuilder.main entry. - AC3 reproducibility: two fires against the same inputs produce byte-identical envelopes. - AC4 latency: median <= 200 ms over 10 runs on a 10k-belief store via the pure rebuild_v14() function (skip-able under AELFRICE_SKIP_LATENCY). Plus targeted tests on the v1.4-only seams: load_rebuilder_config defaults / overrides / malformed TOML / wrong-typed values; the emit_pre_compact_envelope shape; session-scoping invariants; and the hook contract on malformed stdin. All deterministic; full suite runs in ~2.5 s on a workstation.
Updates the design doc to reflect what shipped (rebuild_v14 signature, JSON envelope, [rebuilder] config keys) vs. what remains parked (suppress mode, threshold-mode trigger calibration). Adds an "Unreleased" CHANGELOG entry summarising the v1.4 acceptance work behind issue #139.
The 10k-belief seed phase was taking >5 s on slow CI runners and hitting the project-wide pytest-timeout=5 default. Switching to an in-memory SQLite store lets the seed finish quickly without disk fsync per row; the hot path under test (rebuild_v14) is read-only and behaves identically. @pytest.mark.timeout(60) makes the exception explicit so the next slow runner has clear headroom.
robotrocketscience
force-pushed
the
feat/v1.4-precompact-rebuilder
branch
from
April 28, 2026 07:11
48b8ebe to
69084bc
Compare
This was referenced Apr 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
retrieve()codepath (L0 + L1 + L2.5 in one call); inherits posterior-weighted ranking automatically when [v1.3] Partial Bayesian-weighted ranking #146 lands.session_idmatches the latest transcript turn are surfaced as a dedicated tier between L0 and L2.5/L1.hookSpecificOutput.additionalContextJSON envelope (matching the v1.2.x search-tool hook shape).[rebuilder] turn_window_nand[rebuilder] token_budgetconfig keys in.aelfrice.toml(defaults 50 / 4000);aelf rebuildshares the samerebuild_v14()codepath the hook drives.Acceptance (issue #139)
additionalContextwith locked + session-scoped + retrieve() hits, ordered as locked → session-scoped → L2.5/L1.additionalContextwritten. Tool path unaffected.tests/test_context_rebuilder_hook.py::test_ac4_median_latency_under_200ms_on_10k_belief_store(skip-able underAELFRICE_SKIP_LATENCY=1).aelf setup --rebuilderinstalls the PreCompact hook idempotently (already shipped at v1.2.0a0; carried forward unchanged).aelf rebuild(hidden CLI) invokes the same logic — manual fire of the hook for testing.Test plan
uv run pytest -q --ignore=tests/regression— 1315 passed, 2 skipped (~15s).uv run pyright src/aelfrice/context_rebuilder.py— strict-clean (0 errors).tests/test_context_rebuilder_hook.pycover ordering, edge cases, reproducibility, latency, the[rebuilder]config parser, the JSON envelope shape, and session-scoping invariants.test_hook_pre_compact.pyupdated to parse the JSON envelope; old "no-turns surfaces L0" assertion replaced with the new "no-turns is silent" contract.test_context_rebuilder.py(legacyrebuild()API) untouched and passing.What is NOT in this PR
retrieve()— used as a black box.