Skip to content

fix(provider-acp): declare manual compaction support for omp - #2293

Open
bradhallett wants to merge 2 commits into
get-bb:mainfrom
bradhallett:fix/acp-compaction-409
Open

fix(provider-acp): declare manual compaction support for omp#2293
bradhallett wants to merge 2 commits into
get-bb:mainfrom
bradhallett:fix/acp-compaction-409

Conversation

@bradhallett

Copy link
Copy Markdown
Contributor

What was wrong

The provider-acp bridge already serves manual compaction — bb's compact
affordance sends a standalone builtin /compact mention, which the bridge
runs as the agent's own /compact command via session/prompt and reports
through the acp/compaction/* envelopes — but the acp-omp provider
declaration still carried the ACP tier default supportsManualCompaction: false. compactThreadContext therefore answered 409 Provider "acp-omp" does not support manual context compaction before the bridge was ever
consulted, hiding the affordance and failing plugin compactThread RPCs.
acp-opencode already overrides the same flag; omp accepts the same
/compact maintenance prompt, so the declaration was simply stale.

What changed

  • plugins/provider-acp/server.ts — the acp-omp entry overrides
    supportsManualCompaction: true on top of ACP_BASE_CAPABILITIES,
    exactly matching the existing acp-opencode pattern. No new abstraction;
    the routing itself was already implemented (startCompaction in
    src/bridge.ts). Cursor, Grok Build, and Hermes Agent stay false.
  • apps/server/test/public/public-thread-compaction.test.ts — new case:
    compacting an acp-omp thread returns 200 and dispatches exactly one
    turn.submit carrying createStandaloneBuiltinCompactCommandInput() with
    resumeContext.providerId "acp-omp" — the input the bridge recognizes and
    routes to startCompaction. The genuinely-unsupported provider 409
    (acp-cursor) and the active-thread 409 stay covered.
  • apps/server/test/services/plugins/first-party-provider-plugins.test.ts
    the acp-omp expectation-table entry tracks the flipped capability.
  • No wire, protocol, CLI, or doc surface changes.

How you verified

  • Traced the gate end-to-end at base: compactThreadContext
    providerRegistry.supportsManualCompaction("acp-omp") → plugin
    registration's declared capabilities (supportsManualCompaction: false
    via ACP_BASE_CAPABILITIES) → 409; with the flip, the registry answers
    true and the request proceeds down the same turn.submit path the
    passing pi case exercises (the test harness registers the real
    first-party declarations, so the public test observes the actual
    declaration).
  • Fail-before/pass-after executed: pnpm exec turbo run test --filter=@bb/server
    — 1923 tests, 1922 passing; the single failure
    (test/app/install-machine-script.test.ts) reproduces identically on a
    pristine main checkout at fff3ae8 (environmental, pre-existing).
    Mutation check: reverting only the supportsManualCompaction declaration
    makes exactly the two updated tests fail (the new public 200-path case and
    the first-party capability table), 1923 pass again with the flip restored.
  • pnpm exec turbo run typecheck lint --filter=@bb/server --filter=bb-plugin-provider-acp
    green; pnpm exec oxfmt --check green on all three touched files.
  • Bridge-side /compact routing was already covered by
    plugins/provider-acp/src/bridge/bridge.test.ts ("runs the builtin
    /compact command as compaction, not as a prompt"; failure and refusal
    paths included) — unchanged by this PR.

Fixes #2290

AGENT GENERATED

@bradhallett

Copy link
Copy Markdown
Contributor Author

Live production evidence that the bridge compaction path works end-to-end for acp-omp — gathered today (2026-08-22) on a real thread, independent of this PR's tests.

A local auto-compaction plugin (context-compact) queues /compact for busy threads instead of calling the direct RPC. On thread thr_4tm7g4ie78 (provider acp-omp, OMP 17.4.1) the queued command drained at the turn boundary and executed a real compaction through the provider:

14:31:39Z  plugin log: auto-compact thr_4tm7g4ie78: 73111 tok (7%) → queue
           (idle acp-omp threads in the same sweep: "provider acp-omp has no
            manual compaction; skipping its threads" — the 409 gate)
14:36:50Z  turn/completed (prior turn ends)
14:36:50Z  client/turn/requested: "/compact" (builtin command mention)
14:36:50Z  turn/started → item/started contextCompaction → turn/input/accepted
14:38:17Z  thread/compacted → turn/completed

Sequence numbers on the thread's event log: 19648 (prior turn/completed), 19649–19652 (the /compact turn: requested/started/contextCompaction/input-accepted), 19656 (thread/compacted), 19657 (turn/completed). Provider session id 01a027f5-2537-7000-98be-c1612765f2f8 is stable across all four.

Two conclusions:

  1. The turn-input compaction path already works for acp-omp in production — the same path this PR's new public-route test exercises (createStandaloneBuiltinCompactCommandInput → bridge → session/prompt "/compact"). The compaction above completed successfully at 14:38:17Z.
  2. The 409 is purely the declaration-level gate (supportsManualCompaction: false in ACP_BASE_CAPABILITIES) blocking the idle/direct compactThread RPC. Busy threads are servable today only because the queue path never consults that gate.

So the declaration flip in this PR doesn't enable an untested path — it un-gates the direct RPC onto a path production already exercises successfully.

AGENT GENERATED

The provider-acp bridge already serves manual compaction by sending the
agent's own /compact command as a session/prompt maintenance turn, but
the acp-omp declaration kept the tier default supportsManualCompaction:
false, so compactThreadContext answered 409 before the bridge was ever
consulted. Override the capability per agent, matching acp-opencode.

The public compaction suite gains the acp-omp dispatch case (200 with
the standalone builtin /compact turn submitted for the acp provider),
and the first-party capability table tracks the flip.
omp resolves every consumed builtin slash command with end_turn, including
a /compact that printed "Compaction failed: ..." as an ordinary agent
message, so an end_turn compaction prompt is only a shrunk context when
the agent did not spend the turn reporting a failure (get-bb#2290 review).

While the compaction maintenance prompt is in flight the bridge now keeps
the streamed agent message text. On end_turn it classifies the completed
text: the two known no-op messages ("Nothing to compact (session too
small)", "Already compacted" — the same strings pi prints, get-bb#1721) settle
the compaction as skipped, which the translator reports as a
compaction-skipped warning plus a clean turn boundary with no
thread/compacted; any other "Compaction failed:" text fails the turn with
the agent's reason. Detection only runs for the compaction prompt, never
for ordinary agent traffic.
@bradhallett

Copy link
Copy Markdown
Contributor Author

Rework addendum (reply to review of #2293)

Finding 1 (blocking — obsolete server.ts hunk): Addressed by the rebase. The branch now sits on current main (42658f987); the conflict in plugins/provider-acp/server.ts was resolved in main's favor and the one-line capability is re-expressed where #2325 put it: supportsManualCompaction: true on the acp-omp entry of plugins/provider-acp/src/known-agents.ts, exactly as the review's §6 step 1 specifies. The first-party capability table test and the acp-omp 200-path public-route case are ported onto main's layout (rebased commit 6287a8ec0).

Finding 2 (major — false thread/compacted on omp): Addressed in the same PR (new commit f8620a8ea), following the pi/#1721 precedent the review pointed at. While the compaction maintenance prompt is in flight (activePromptKind === "compaction" only), the bridge accumulates agent_message_chunk text; when the prompt ends with end_turn the completed text is classified:

  • "Compaction failed: Nothing to compact (session too small)" / "Compaction failed: Already compacted" (the exact live strings from §5b) → new skipped compaction outcome → translator emits provider.warning with category: "compaction-skipped" plus a completed turn boundary and no thread/compacted — identical treatment to pi's delta translation.
  • Any other "Compaction failed: …" text → turn fails with the agent's own message; no thread/compacted, no success banner.
  • Anything else → unchanged completed + thread/compacted.

Detection is scoped narrowly to the compaction turn and never inspects ordinary agent traffic; the message strings are matched verbatim from the report. Covered by three new tests (two bridge-level against the fake ACP agent — which gained a FAKE_ACP_COMPACT_AGENT_MESSAGE knob to replay omp's message-then-end_turn behavior — and one delta-translation unit test), each verified fail-before/pass-after by mutation:

  • early-return {status:'completed'} before the failure check → both bridge tests fail, including the exact false thread/compacted the report predicted;
  • disabling the skipped→warning mapping → the translation test fails expecting the provider/warning row;
  • reverting the known-agents.ts declaration → the public 200-path test fails with the 409 body and the capability table fails expected false to be true.

Finding 3 (minor — bridge behavior untested): The two bridge-level tests close this gap.

Finding 4 (minor — unrelated reformatting): Dropped during the rebase, but the repo-pinned oxfmt 0.64.0 re-introduces both hunks on main's current copy of the file (main's own blob fails oxfmt --check), so they are kept to stay format-clean; they are pure formatter output, no semantic change.

Finding 5/6 (ok): No wire/daemon/CLI changes; the skipped status is a bridge-internal envelope value (the wire still only carries existing delta kinds), so HOST_DAEMON_PROTOCOL_VERSION stays untouched.

Gates: @bb/provider-bridge-acp + bb-plugin-provider-acp test/typecheck/lint 8/8 green (258 + 76 tests); @bb/server typecheck/lint green, full suite 2005/2006 — the single failure (install-machine-script.test.ts, Abort trap: 6 in a nohup'd host-daemon join) reproduces identically with these changes stashed on clean main; scoped test/public/ + test/services/plugins/ 793/793.

AGENT GENERATED

@bradhallett
bradhallett force-pushed the fix/acp-compaction-409 branch from e1e0599 to f8620a8 Compare August 24, 2026 22:49
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.

compactThread returns 409 for acp-omp although the provider-acp bridge already implements /compact

1 participant