Skip to content

feat(kap-server): move compacting from session.state to agent.state turn - #3712

Merged
sailist merged 1 commit into
MoonshotAI:devfrom
sailist:feat-191-09-10-agent-turn-compacting
Sep 10, 2026
Merged

feat(kap-server): move compacting from session.state to agent.state turn#3712
sailist merged 1 commit into
MoonshotAI:devfrom
sailist:feat-191-09-10-agent-turn-compacting

Conversation

@sailist

@sailist sailist commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

Follow-up to #3532 (flat entity message protocol). Internal protocol adjustment, no linked issue.

Problem

The v3 protocol carried a compacting value on session.state.status that the projection never produced (session state is derived purely from busy → idle | running). Meanwhile, full compaction is an agent-level activity that happens inside a running turn, and subscribers had no way to observe it in real time — compaction.started / compaction.completed bus events existed but were not surfaced on any state entity.

What changed

  • session.state.status narrowed to 'idle' | 'running': the never-produced 'compacting' value is removed from the schema. No runtime behavior change — the projection only ever emitted the two remaining values, so this is backward compatible for consumers.
  • agent.state.turn.status gains 'compacting' (now 'thinking' | 'retrying' | 'acting' | 'aborting' | 'compacting'), an additive enum extension per the open-union evolution rule.
  • The projection now produces it: AgentStateTracker holds a compacting flag driven by the per-agent compaction.started / compaction.completed / compaction.cancelled bus events (observable, already in the projection event union). While compacting, the flag takes precedence over the activity-snapshot phase mapping; when compaction ends the turn status recomputes back to the real phase. compaction.blocked never enters the compacting state. Compaction outside an active turn is not represented (the turn field only exists while running).
  • agent-core-v2 is untouched: the signal is computed entirely at the kap-server projection layer from existing bus events.
  • Tests: the main SessionProjection lifecycle case now drives a blocked → started → completed sequence and asserts compacting is emitted exactly once and the turn returns to acting afterwards (test count unchanged).

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue (external PRs: the issue must have a maintainer's /approve).
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@changeset-bot

changeset-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c6cf9e4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@sailist
sailist merged commit 1814aa7 into MoonshotAI:dev Sep 10, 2026
13 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6cf9e45c0

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

if (this.status !== 'running') return false;
this.status = 'idle';
this.turn = undefined;
this.compacting = false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve compaction state across turn boundaries

When background auto-compaction outlives the turn that started it—a supported scenario in fullCompaction.test.ts—this reset discards the active compaction before any compaction.completed or compaction.cancelled event. If another turn begins while that task is still running, recompute() consequently reports thinking or acting instead of compacting; clear only the turn display here and retain the lifecycle flag until its matching end event.

Useful? React with 👍 / 👎.

private endedAt: string | undefined;
private status: AgentStatus = 'idle';
private turn: AgentStateTurn | undefined;
private compacting = false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Seed compacting when attaching to a live agent

ProjectionService.forSessionLive() creates projections lazily, so the first v3 subscriber can attach after compaction.started has already fired. Because this tracker always initializes the flag to false and only subsequent bus events update it, recovery and live state never expose compacting for that in-flight operation; the eventual completion merely recomputes an ordinary phase. Seed the flag, along with the current turn snapshot, from the live agent services when tracking an existing agent.

Useful? React with 👍 / 👎.

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