Skip to content

feat: persist the live fold slot across restarts (fixes #130) - #131

Merged
ranxianglei merged 1 commit into
2026-08-22_openai-system-hoistfrom
2026-08-22_fold-persist
Aug 22, 2026
Merged

feat: persist the live fold slot across restarts (fixes #130)#131
ranxianglei merged 1 commit into
2026-08-22_openai-system-hoistfrom
2026-08-22_fold-persist

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Fixes #130. Stacked on #129 (base = its branch; retargets to master automatically when it merges).

Problem

At restart the wire payload is unavailable until the first provider request, so primeFold folds a session-view mirror. The view→wire projection is host-owned (pi-ai transformMessages + convertMessages: cross-model thinking demotion, developer→user remap, empty-message drops) — the mirror lands in a different ref/fingerprint space, every in-stream compress replay failed the span guard, and /acp showed Blocks: none until the first provider request refolded the real wire. Live evidence: 1988 mirror pieces vs 1692 live pieces, 0/14 anchors matched.

Fix

Checkpoint the live fold slot to disk and restore it at session_start, before any mirror runs:

  • acp-kernel/persist (0.0.40, kernel refactor: delegate primeFold mirrors to acp-kernel mirror constructors (0.0.35) #126) provides the mechanism: atomic writes (temp+rename, EPERM/EBUSY retry), debounce, per-id serialization, corrupt-tolerant load. omp (src/fold-persist.ts) provides the policy: dir (~/.omp/acp-omp-folds, env ACP_OMP_FOLD_DIR), schema v1, validation, when to save.
  • Restored identities live in the wire's own content-hash space (coreIdentity is a pure function of content), so the first live fold re-validates the restored slot via the normal LCP check; a stale checkpoint degrades to the ordinary re-fold — never worse.
  • Zero-block checkpoints are neither persisted nor restored: they carry nothing the fresh slot lacks, but claiming one suppresses the mirror fallback (found as a session_switch regression during testing — the exact 重启后 /acp 谎报 Blocks: none:primeFold 镜像与 live wire 指纹空间分歧(折叠状态无持久化) #130 symptom from the wrong direction).
  • Crash without shutdown (no flush) degrades to the primeFold mirror — the pre-persistence behavior, unchanged.
  • foldPersistence config ({enabled, dir}, boolean shorthand, default on) turns it off entirely.
  • session_shutdown flushes synchronously before forgetSession — the host may exit as soon as the handler returns.

Tests (7 new, tests/fold-persist.test.ts)

restart e2e (block visible before the first provider request, survives it), crash fallback to mirror, zero-block guard, corrupt checkpoint skip, disabled persistence, live-slot no-clobber on session switch back, incremental LCP on extended history. scripts/test.ts now isolates ACP_OMP_FOLD_DIR per run — restored snapshots from earlier runs otherwise marked replayed compress calls as already-applied. Full suite green (30 files), typecheck clean.

@ranxianglei
ranxianglei force-pushed the 2026-08-22_openai-system-hoist branch from 9c131f5 to 0467e3f Compare August 22, 2026 16:13
@ranxianglei
ranxianglei force-pushed the 2026-08-22_fold-persist branch from 4894171 to 49854f9 Compare August 22, 2026 16:21
@ranxianglei
ranxianglei force-pushed the 2026-08-22_openai-system-hoist branch from 0467e3f to 56e586d Compare August 22, 2026 16:30
Checkpoint the provider-mode FoldSlot to disk via acp-kernel/persist
(StateStore) and restore it at session_start, before the primeFold
mirror runs.

Why: at restart the wire payload is unavailable until the first provider
request, so primeFold folds a session-VIEW mirror — a different
fingerprint space than the live wire fold (host transformMessages +
convertMessages reshape the view). Every in-stream compress replay then
failed the span guard and /acp showed "Blocks: none" until the first
provider request refolded the real wire (issue #130).

The restored identities live in the WIRE's own content-hash space
(coreIdentity is a pure function of content), so the first live fold
re-validates the restored slot via LCP; a stale checkpoint degrades to
the normal re-fold, never worse. Zero-block checkpoints are neither
persisted nor restored — they carry nothing the fresh slot lacks but
would suppress the mirror fallback (issue #103 regression found in
tests). Crash without shutdown also degrades to the mirror.

- new src/fold-persist.ts: policy layer over acp-kernel/persist
  (dir/env/config, schema v1, snapshot validation, restore w/ forward-
  compat merge); default dir ~/.omp/acp-omp-folds, env ACP_OMP_FOLD_DIR
- runtime: restoreFold/scheduleFoldSnapshot/flushFoldSync; snapshot at
  live fold + turn commit + compress commit; flushSync at
  session_shutdown before forgetSession
- config: foldPersistence {enabled, dir} (boolean shorthand, default on)
- scripts/test.ts isolates ACP_OMP_FOLD_DIR per run (restored snapshots
  from earlier runs marked replayed calls as already-applied)
- tests/fold-persist.test.ts: restart e2e pre-LLM, crash fallback,
  zero-block guard, corrupt skip, disabled, switch-back no-clobber,
  incremental LCP on extended history

Requires acp-kernel 0.0.40 (persist subpath, kernel PR #126).
@ranxianglei
ranxianglei force-pushed the 2026-08-22_fold-persist branch from 49854f9 to 95285de Compare August 22, 2026 16:30
@ranxianglei
ranxianglei merged commit 4045aca into 2026-08-22_openai-system-hoist Aug 22, 2026
ranxianglei added a commit that referenced this pull request Aug 22, 2026
persist the live fold slot across restarts (fixes #130)
@ranxianglei ranxianglei mentioned this pull request Aug 22, 2026
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.

1 participant