Skip to content

Session Strategy: decouple always-visible session state, policy intent, and client capabilities #1329

Description

@mindfn

Classification

This is a product-contract follow-up to #1208 / #1209 and the completed F033 Session Strategy work. It is not part of #1209's context-capacity fix.

#1209 owns the unified member Context Window, removal of overlapping context-budget controls, one invocation capacity snapshot, authoritative usage normalization, carrier binding, and the corrected lifecycle denominator. This issue owns the later strategy/state semantics.

Problem

The current product model mixes three independent concerns:

  1. Session state and observability — which session is active, its Context Window/usage, compression history, and prior session nodes.
  2. User policy intent — handoff, compress, or hybrid.
  3. Client/carrier capability and control boundary — whether the effective input ceiling and carrier binding are proven, whether current-context usage or native compaction events are observable, and whether session rotation/bootstrap is executable.

That coupling creates misleading behavior:

  • sessionChain=false hides or disables state that should remain observable.
  • unsupported or unobservable strategies may be silently rewritten to handoff.
  • compressionCount ?? 0 can present unknown telemetry as a confirmed zero.
  • capability gating can alter the configured policy or runtime action instead of reporting execution status.
  • strategy changes are not described clearly for the current active session versus a future session.
  • unmanaged external sessions can appear actionable even though Cat Cafe has no invocation/control boundary.

Target contract

1. Session State is always present

There is no user-facing Session Observability switch.

The product always attempts to expose:

  • current logical/runtime session and historical chain nodes;
  • effective Context Window/input ceiling plus source/confidence;
  • current used context as exact, approximate, or unavailable;
  • compression count as a known number or null/unknown;
  • configured policy and its source;
  • execution status as active, degraded, or unavailable.

A session that has never rotated is a one-node chain. Existing sessionChain configuration becomes legacy migration input and no longer suppresses baseline state collection or display.

Workspace resume provenance remains a separate baseline binding concern; see #1326.

2. Policy expresses intent only

Policy Clowder action
handoff At the configured threshold, seal the active session, start a new session, and bootstrap continuity—but only when the complete actionability proof in §3 is satisfied.
compress Take no proactive lifecycle action; let the client manage native compaction.
hybrid After revision-scoped, atomically observed native client compactions reach N, hand off to a new session.

Clowder does not currently issue an active compaction request. A future managed-compaction feature must be a separate policy, not hidden inside handoff or the current compress.

3. Capability reports execution status; it never rewrites policy or action

handoff=active requires one invocation-bound proof containing all of:

  • a resolved, actionable effective input ceiling / Context Window from fix: unify member context capacity and lifecycle (#1208) #1209;
  • a carrier binding proving that denominator belongs to the same effective model/carrier invocation;
  • authoritative current-context usage from that invocation;
  • session rotation capability;
  • continuity bootstrap capability.

Missing any item keeps the stored and effective policy as handoff, reports unavailable, and allows no threshold action. Stable missing-capability reasons include:

  • effective_input_ceiling
  • carrier_binding
  • authoritative_usage
  • session_rotation
  • continuity_bootstrap

Other policy rules:

  • compress remains passive regardless of telemetry availability. If the client never compacts, Clowder makes no false promise that it will.
  • hybrid without observable compaction events keeps the stored/effective selection, reports degraded, and behaves passively like compress.
  • unknown compression telemetry remains unknown; it is never normalized to zero.
  • no unsupported policy may rewrite the persisted value, change the effective policy, or execute a handoff action through a fallback path.

Capability dimensions remain independent: effective input ceiling, carrier binding, authoritative current usage, native compaction support/control, compaction event signal, session rotation, and continuity bootstrap.

4. Policy changes apply to the active session at invocation boundaries

Each invocation gets an immutable policy snapshot { policy, source, revision, changedAt }. Configuration changes do not mutate an invocation already in flight.

The next invocation applies the new policy to the same active session:

  • handoff → compress: stop new proactive threshold seals;
  • compress → handoff: begin threshold evaluation only when the complete §3 actionability proof exists;
  • switching to hybrid: start a new policy-local observation epoch; historical unknown remains unknown.

An already completed seal is irreversible and is not undone by a later setting change.

5. Legacy migration is dual-read / single-write

Read precedence is:

runtime override > explicit member strategy > breed strategy > legacy sessionChain migration > provider/global default

  • sessionChain:false with no explicit strategy derives { policy: 'compress', source: 'legacy_session_chain_false' } at read time.
  • the derived value is not persisted as an explicit user choice.
  • any explicit handoff, compress, or hybrid value wins over the legacy boolean.
  • new UI/API writes strategy only and rejects writes to sessionChain with migration guidance.
  • the legacy boolean remains byte-for-byte unchanged solely as rollback input until a separately reviewed cleanup after the rollback window.
  • missing historical compressionCount remains null/unknown; migration never creates an observed zero or reconstructs history.

6. Managed execution and external-direct transparency are different contracts

Cat-Cafe-managed serial, parallel, CLI, ACP, and managed external-runtime invocations share the same immutable policy snapshot, capability/evidence state machine, and evidence-to-action rules.

IDE-direct or otherwise unmanaged external runtime sessions guarantee only state/policy/status projection. Without a Cat Cafe invocation and control boundary:

  • execution status is unavailable with stable reason managed_invocation_boundary;
  • no threshold, compression-count, rotation, or bootstrap action is allowed;
  • telemetry may update the always-visible ledger but cannot become execution authority.

7. Lifetime telemetry and hybrid policy progress are separate

Public/API lifetime telemetry is compressionCount: number | null; null means unknown and 0 means an observed zero.

Hybrid sealing consumes only revision-scoped persistent progress:

type HybridProgress = {
  policyRevision: string;
  observedCount: number;
  startedAt: string;
};

Each observed compaction event is atomically attributed to the active policy revision. Lifetime compressionCount is display telemetry and can never substitute for HybridProgress. A first observed event may advance policy progress to 1 while lifetime history correctly remains unknown.

User surface

Keep the member editor conceptually small:

  1. Context Window — Auto / Manual plus resolved value/source/confidence.
  2. Session State / Chain — always-visible runtime state, not a toggle.
  3. Session Strategy — handoff / compress / hybrid.
  4. Execution status — active / degraded / unavailable with the exact missing capability or control-boundary reason.

The capability matrix remains internal. Users see concise stable status reasons, not provider implementation details.

Non-goals

  • Do not add these semantics to fix: unify member context capacity and lifecycle (#1208) #1209.
  • Do not add active managed compaction.
  • Do not conflate workspace resume binding with Session Chain.
  • Do not invent context usage from local prompt estimates.
  • Do not reconstruct unknown historical compression counts.
  • Do not grant execution authority to unmanaged external sessions.

Dependencies and lineage

Acceptance criteria

  • Session state/chain remains visible for members previously configured with sessionChain=false.
  • A never-rotated active session renders as a one-node chain.
  • compress never calls the session sealer at warn, action, budget-exhausted, or hook thresholds.
  • handoff=active requires the same invocation's actionable effective input ceiling, carrier binding, authoritative current usage, rotation capability, and continuity bootstrap; any missing proof reports unavailable and takes no threshold action.
  • hybrid seals only when revision-scoped, atomically observed HybridProgress.observedCount reaches N.
  • lifetime compressionCount: number | null is telemetry only and never substitutes for hybrid policy progress.
  • hybrid with unavailable compaction events remains passive and reports degraded.
  • no configuration/runtime path rewrites the persisted strategy, changes the effective policy, or executes an unsupported policy as handoff.
  • unknown compression telemetry remains distinct from observed zero in API, prompt hints, persistence, and UI.
  • strategy changes take effect on the next invocation of the current active session.
  • legacy migration is dual-read/single-write: legacy false derives source-tagged compress without persistence, strategy-only writes reject the boolean, rollback input remains unchanged, and missing counts remain null.
  • Cat-Cafe-managed serial, parallel, CLI, ACP, and managed external-runtime paths share one policy-state transition contract.
  • unmanaged external-runtime sessions project state/policy/status as unavailable with managed_invocation_boundary and execute no lifecycle action.
  • completed seals remain irreversible and runtime IDs remain late-bound metadata.

Provenance

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedMaintainer accepted: ready for implementation/mergeenhancementNew feature or requesttriagedMaintainer reviewed, replied, and made an initial triage decision

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions