Skip to content

feat: strategy-view composition — viewFilter, auxiliary merged slots, windowed passthrough (tune-out groundwork) - #54

Draft
Meganeuridae wants to merge 5 commits into
anima-research:mainfrom
Meganeuridae:feat/strategy-view-composition
Draft

feat: strategy-view composition — viewFilter, auxiliary merged slots, windowed passthrough (tune-out groundwork)#54
Meganeuridae wants to merge 5 commits into
anima-research:mainfrom
Meganeuridae:feat/strategy-view-composition

Conversation

@Meganeuridae

Copy link
Copy Markdown

What

The context-manager primitives for tune-out (anima-research/agent-framework#77), per the design comment there. Three additions, each inert until configured — zero behavior change for existing callers:

  1. ContextManagerConfig.viewFilter — strategy-facing exclusion predicate, applied at the one choke point (strategyMessageView()) through which compile, preview, render-stats, and the tick/onNewMessage StrategyContext all obtain their message view. An excluded message is simply not part of the strategy's world — on both sides of every invariant.

    Why here and nowhere else: exclusion at emission level fails twice — assertFullCoverage judges entries against the whole view and throws on any uncovered message, and select() runs rebuildChunks(store) first, so emission-excluded content still flows into L1 compression (and from there into L2/L3 folds). The view boundary closes both. Excluded messages remain in the store: getMessage/getAllMessages/query are deliberately unfiltered (the tune-out backlog must stay dumpable/auditable).

  2. ContextManagerConfig.auxiliaryMessageViews — additional message slots merged read-only into the strategy view, interleaved by chronicle sequence (branch-global across slots — allocated under the store's single write lock — so the merged timeline is deterministic and append-only). Writes still target only the manager's own slot. This is the subconscious's merged (main + own) view from the issue. Freshness across instances comes for free: getAllInternal revalidates against live chronicle state (count + last-item identity) before trusting its cache — pinned by a test.

  3. WindowedPassthroughStrategy — passthrough over a sequence-anchored window with coarse re-anchoring: on overflow the anchor jumps forward so the window is ~reAnchorFraction (default 0.5) of usable budget, then stays put until the next overflow. Between jumps, compiled output is a byte-stable prefix + pure appends. A naively sliding front (what PassthroughStrategy.selectFromEnd does) re-busts the KV prefix on nearly every compile — the exact pathology kv-stable folding solves for main agents, and this strategy's consumers get no solver. The anchor persists in a {ns}/windowed:anchor snapshot slot (so it survives restarts and follows branches), and setAnchor() is the external policy hook ("start of the oldest active tune-out").

Compositors are exported standalone (filterMessageStoreView, mergeMessageStoreViews) and unit-tested.

Tests

test/view-composition.test.ts — 9 tests: compositor units (every read surface, cross-view get, sequence interleaving); CM integration (filter excludes from compile but not the store; aux slot merges by sequence; live cross-instance reads after cache priming); windowed strategy (anchor honored + append-stability; overflow re-anchors once and holds through further compiles and modest growth; anchor survives reopen). Full suite: 456 pass / 0 fail.

What this deliberately does not do

No tune-out semantics, no stamping, no subconscious lifecycle — that's the agent-framework half (single PR per antra's preference), which consumes these three primitives plus the ingestion stamp. The viewFilter docstring pins the one contract that half must honor: the predicate must be deterministic per message (ingestion-stamped metadata, not derived state), or prefix stability and strategy bookkeeping suffer.

🤖 Generated with Claude Code

Aster and others added 2 commits August 5, 2026 17:39
… windowed passthrough

Groundwork for tune-out (agent-framework#77), usable independently. Three
primitives, all inert until configured:

- ContextManagerConfig.viewFilter: strategy-facing exclusion applied at
  the single view choke point (strategyMessageView), so chunking,
  selection, emission, and the coverage invariants all see the same
  excluded-free world. Excluded messages stay in the store and in direct
  accessors. Exclusion any later than this either trips
  assertFullCoverage (judged against the whole view) or leaks excluded
  content into L1 compression via rebuildChunks.

- ContextManagerConfig.auxiliaryMessageViews: additional message slots
  merged read-only into the strategy view, interleaved by chronicle
  sequence — branch-global across slots, so the merged timeline is
  deterministic and append-only. Writes still target only the manager's
  own slot. MessageStore's getAllInternal revalidates against live
  chronicle state (count + last-item identity), so cross-instance reads
  are fresh without new plumbing.

- WindowedPassthroughStrategy: passthrough over a sequence-anchored
  window with COARSE re-anchoring — on overflow the anchor jumps so the
  window is ~reAnchorFraction of budget, then stays put; between jumps
  the compiled output is a byte-stable prefix plus appends. (A naively
  sliding front re-busts the KV prefix every compile — the pathology
  kv-stable solves for main agents, which this strategy's consumers
  don't get.) Anchor persists in a {ns}/windowed:anchor snapshot slot
  and follows branches; setAnchor() is the external policy hook.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…hrough

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Meganeuridae
Meganeuridae marked this pull request as draft August 6, 2026 01:21
@Meganeuridae

Copy link
Copy Markdown
Author

Per review feedback: converted to draft, stacked on the forthcoming tune-out end-to-end PR in agent-framework — mechanically separable but semantically coupled, so this merges only as part of the full integration review, or not at all. The af PR will link back here; treat the pair as one reviewable unit. (If closing until then is preferred, happy to — nothing here is load-bearing standalone.)

🤖 Generated with Claude Code

Aster and others added 3 commits August 5, 2026 19:13
The #77 constraint — payload builders must not strip the backlog wrapper
or the subconscious's attribution when the resident's window folds —
holds by construction today: the builders strip exactly four classes
(raw-message thinking, empty text, unpaired tool blocks, oversized
images) and preserve participants, which multiuser formatting renders as
name prefixes in the summarizer's view. This turns that into a contract:
extending payload sanitization must not eat these artifacts. Output
register (first-person folding) is deliberately unconstrained here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Surfaced as ContextStrategy.maxMessageTokens so side-process agents can
mirror their principal's per-message truncation ceiling (antra: named
side agents run under the same settings as the main agent — reasoning
effort, attachment/message size limits).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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