Skip to content

feat(hooks): /compact focus steers distiller output + relay arc ranking - #114

Merged
mahmoudimus merged 1 commit into
mainfrom
feat/compact-focus
Jul 21, 2026
Merged

mahmoudimus merged 1 commit into
mainfrom
feat/compact-focus

Conversation

@mahmoudimus

Copy link
Copy Markdown
Owner

What

Phase 2 of the compact relay: the text you type after /compact now does double duty. Claude Code natively uses it to steer the summary (docs: "the summary keeps what you choose"); simba now uses the same text — received by the PreCompact hook as custom_instructions — to steer what the relay brings back across the boundary.

How

  • Persist: PreCompact stores the (300-char-truncated) focus as compactFocus in the export metadata.json it already writes; key omitted entirely for auto-compact. SessionStart(compact) reads it back for the same session_id.
  • Rank the relay arcs: with a focus present, the compact-branch injection fetches 3×K candidates (one bounded LIMIT query), scores each arc by deterministic token overlap (lowercase word tokens ≥3 chars, set intersection — new shared transcripts/focus.py, no LLM/embeddings), orders by (score, recency) and injects the top K, prefixed with Compaction focus: <text>. No focus → byte-identical to today.
  • Focus the distiller: simba transcript distill --focus TEXT reorders the output document's arc listing by the same scoring (focus-matched arcs first); the failure_arc sidecar is untouched. The PreCompact spawn forwards the focus automatically.

Tests

Red-first across all three legs: persistence (manual vs auto), ranking (relevance beats recency only when focused; caps respected; no-focus byte-identity), distiller ordering (byte-identical without focus). Full suite exit 0, ruff clean.

/compact <text> arrives as custom_instructions on PreCompact's stdin only
(SessionStart never sees it), so it's persisted -- truncated to ~300 chars
-- into the session's exported metadata.json as compactFocus. Two readers
consume it:

- SessionStart(source="compact") reads the persisted focus and ranks the
  compact-relay arc block by deterministic token-overlap against each
  candidate arc's signature+fix text (transcripts/focus.py), fetching up
  to 3xK candidates via the existing bounded LIMIT query. A "Compaction
  focus: <text>" line is prepended when a focus is present. No persisted
  focus -> today's pure-recency behavior, byte-identical.

- The over-cap detached distiller spawn forwards the same focus as
  --focus (new simba transcript distill flag); distill_transcript reorders
  its <failure-arcs> output section by the same scoring, never touching
  the failure_arc sidecar schema or what gets stored. No focus -> byte-
  identical output.

Scoring is plain lowercase word-token overlap (tokens <3 chars dropped) --
no LLM, no embeddings.
@mahmoudimus
mahmoudimus merged commit 0f795dd into main Jul 21, 2026
1 check 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.

1 participant