Skip to content

fix(refresh): preserve add sequence through continuity - #710

Merged
atomchung merged 1 commit into
mainfrom
codex/issue-660-refresh-add-continuity
Aug 1, 2026
Merged

fix(refresh): preserve add sequence through continuity#710
atomchung merged 1 commit into
mainfrom
codex/issue-660-refresh-add-continuity

Conversation

@atomchung

Copy link
Copy Markdown
Owner

Closes #660

User before → after

Before: a routine holdings refresh for a position that had never been sold preserved its cycle_id, but rebuilt the adopted snapshot anchor with add_count: 0. The derived decision_cursor therefore became null and a previously captured add reason could be asked again.

After: only the existing #539 proven-continuity branch carries a positive engine-known add_count. The ledger remains the single reader that derives decision_cursor; the next canonical BUY advances that count, while a sell/rebuy starts at zero.

Root cause and scope

The #539 relink path carried cycle start and sequence but omitted the existing active cycle's add sequence. The fix threads the same internal metadata through:

  • book_refresh.carry_recorded_starts after its continuity proof;
  • snapshot validation and durable anchor serialization;
  • ledger derivation and the snapshot prepare projection that feeds the existing question deduplicator.

It does not replay pre-anchor history, add a memory object/event stream, or change weights, cost basis, valuation, concentration, or other investment arithmetic.

Compatibility and recovery

  • add_count is engine-assigned: caller-supplied add_count and decision_cursor fail closed.
  • Zero remains omitted, preserving legacy ordinary-anchor identities.
  • Failed adoption writes nothing; repeated adoption carries the scalar without incrementing it.
  • Sale/re-entry derives a fresh cycle and zero count.
  • The field is additive: an emergency revert leaves existing anchors readable; it does not delete or rewrite historical rows.

Evidence

  • python3 tests/run_all.py — pass.
  • python3 tests/persona_sweep.py --baseline /tmp/fomo-kernel-660-baseline/skills/fomo-kernel/engine — pass; Markdown and HTML are byte-identical for all 156 rendered persona cards.
  • Production-shaped regression covers opening anchor → two recorded adds → captured decision → routine refresh adoption → real review.py prepare, confirming the carried cursor is retained and the existing question reader marks it already_captured.
  • Focused regressions cover the third BUY becoming count 3, sold/rebought reset, external metadata refusal, retry idempotency, and [bug·contract·M1-prep] Host entry points still teach retired incomplete-snapshot semantics after #562 #549 re-derive behavior.
  • Mutation evidence: temporarily disabling _carry_add_count makes test_a_continuous_cycle_keeps_its_engine_known_add_sequence_through_refresh fail with the adopted holding at add_count: 0 and no cursor; the implementation was restored before the passing suite.

Non-goals

No owner-live M1 acceptance is claimed here, and this PR does not touch #610/#683, rationale memory, #590 research, weekly/news/scheduler work, ETF look-through, or card redesign.

Copy link
Copy Markdown
Owner Author

Independent review — no blocking findings

Reviewed PR head cb340427a4b84e54bf3c573da9bc2f1db47481d1 against #660 and current #27 routing.

  • Correctness: add_count travels only through the existing [bug·design·P2] Every new snapshot declaration re-asks for theses it was already given #539 proven-continuity branch; decision_cursor remains derived by ledger.derive_holdings rather than becoming a second persisted fact.
  • State integrity / recovery: routine adoption and retry carry rather than increment; sale/re-entry resets; malformed persisted values degrade with a named integrity finding; failed validation appends nothing.
  • Agent boundary: caller-supplied add_count is refused, and decision_cursor is neither accepted nor serialized.
  • Compatibility: zero remains absent, old anchors remain readable, positive carried metadata participates in the existing snapshot position payload, and no migration or destructive rewrite is introduced.
  • UX consequence: a routine holdings refresh no longer reopens an already captured add-decision question.
  • Scope: no portfolio arithmetic, card output, provider, new memory object, or broad ledger refactor.
  • Evidence: production-shaped prepare/dedup trajectory; refresh, rebuy, retry, third-BUY and external-input regressions; persona byte parity; mutation witness; full CI green on Python 3.11 and 3.12.

GitHub does not allow the repository author to submit an approving review on their own PR, so this conversation comment records the review result. Merge is authorized by the owner in the current session.

@atomchung
atomchung merged commit 8825e5e into main Aug 1, 2026
3 checks passed
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.

[bug·P2] Adopting a book resets the add count of a position that was never sold

1 participant