Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,26 @@ reconciliation, startup, or session switching. Preserve global delivery for
newly appended live errors and active-scope delivery for live agent-exit
warnings. See `docs/notifications.md`.

Git and GitHub notification-bar events are live and user-triggered only. Publish
observed successful commit, push, pull, fetch, sync, merge, repository-publish,
and PR mutation results; never notify from polling, catalogue refresh, startup,
or restored state. The Git Workspace PR launcher badge counts only observed open
and draft PRs, excluding closed and merged PRs. See `docs/notifications.md` and
`docs/github-pull-requests.md`.

Active Git surfaces silently refresh the bounded GitHub pull-request catalogue
once per minute so PRs created or changed by other users update the Browser and
open-count badge. Keep that poll single-flight, preserve selection when possible,
and never turn polled transitions into notification-bar events.

Git tabs retain meaningful unfinished UI state across inactive-tab unmounts in
bounded process-session memory keyed by exact outer tab/worktree identity. Keep
commit/amend drafts, PR creation fields/step, PR Browser location, review summary,
and queued inline comments; clear the applicable draft on explicit cancel or
successful submission. Never retain credentials, mutation locks, destructive
confirmations, or infer repository outcomes from UI memory. See
`docs/git-workspace.md` and `docs/github-pull-requests.md`.

Inactive standalone terminal tabs stay mounted to preserve their PTYs, but must
pass `active={false}` through `TermColumn` to `XTermPane`. Buffer their output
without `term.write()`, then refit and replay it with bounded frame work and
Expand Down Expand Up @@ -272,6 +292,16 @@ while Electron Background Brain owns it.

Remote-access credentials are authority boundaries. Pairing tokens must remain short-lived, memory-only, and single-use. Persist only device-session digests in owner-only atomic stores; enforce expiry and revocation. Browser HTTP/WebSocket origins must match exactly or be explicitly configured—never reflect arbitrary `Origin`/forwarded headers. Keep authentication limiters bounded, and do not hardcode CJ's `crewcode.logixhub.icu` deployment as a default Hub URL.

Hub-connected web Settings lists every machine enrolled to the authenticated owner and
keeps reversible disablement distinct from permanent revocation. Disable must persist
the authority suspension, reject heartbeats/tickets/new Brain relays, close existing
Brain and browser relay sessions, and preserve the machine credential for explicit
re-enable. Enable clears the suspension but reports offline until a fresh Brain relay
and heartbeat are observed. Keep these same-origin, session/CSRF-protected Hub control
operations behind the typed CrewCode client; never route them through the selected
Brain, expose Hub credentials, show the surface in direct-server/Electron-only
Settings, or infer machine availability from the mutation response.

Browser delegation keeps its agent-facing endpoint Brain-loopback and bearer-scoped;
delegate requests, editor watches, and LSP handles remain bound to the authenticated
browser session that owns them. Browser plugin iframes load only approved plugin
Expand Down Expand Up @@ -340,6 +370,8 @@ YuHeard PTY integration must remain bundle-safe. `PtyService` receives the activ

CrewCoder agent profiles are separate from CrewCode execution modes. Show the desktop model-row profile picker only when the installed CrewCoder provider is active; disable it during a running turn, persist the optional session-scoped `crewcoderMode`, omit `--mode` for Configured default, and pass only `general | crewcoder | plugin | extension` to `crewcoder acp --mode`. A concrete profile locks the underlying CrewCode permission policy to Build and disables Ask/Plan/Build/Full on desktop and phone; Configured default re-enables those controls. Never retain a hidden prior Ask, Plan, or Full Access policy under a concrete profile. When the concrete `crewcoder` profile is active, show the separate desktop approval picker and persist `crewcoderApprovalMode`; expose only CrewCoder's `review`, `always`, `never`, `full-access`, and `sandboxed` values, with `review` as the fail-closed default. Treat approval changes as immutable launch authority: disable them during a running turn, drop only the idle bridge, include the value in custody, and native-resume on the next prompt. Never suppresses prompts but continues to block dangerous calls; Sandboxed applies the native sandbox policy where supported; Full access bypasses CrewCoder approval requests and dangerous-command blocking, so label that risk truthfully and never imply CrewCode Build still interposes. Never route Ask/Plan/Build/Full into CrewCoder's `--mode`. The `crewcoder` profile's plan gate is CrewCoder-owned: project `crewcoder_clarify` / `crewcoder_propose_plan` into the activity overlay and send `/approve-plan` as a prompt, never as a tool-permission Allow/Deny. See `docs/crewcoder-provider.md`.

CrewCoder manual compaction is capability-gated. Expose the bridge `compact()` path only after observing exact `initialize._meta["crewcoder/sessionCompact"].method === "session/compact"`; older CrewCoder versions retain summary-reset. Call the advertised method only while idle and keep CrewCoder's durable session id and ACP child after success. Use the returned summary to replace CrewCode's replay shard and add the visible compact-summary card while retaining the full rich display transcript. Treat `_crewcoder/compaction_update` as authoritative, never infer a duplicate from usage, never fabricate a turn for idle progress, and do not clear usage/replay when the provider reports a skipped compact. See `docs/crewcoder-provider.md` and `docs/conversation-storage.md`.

Provider context handoff is initiated from the Solo Chat header or `/handoff`. Its Used chats tab mirrors the current workspace's live Sessions catalogue across chat tabs; starting either a new or used destination closes the card immediately and moves progress/failure feedback to the destination meter. Preserve each selected destination's owner tab/worktree, existing provider/model/effort locking, and disposable destination-provider summary flow documented in `docs/provider-context-handoff.md`.

## Plugin platform notes
Expand Down
19 changes: 16 additions & 3 deletions docs/conversation-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,24 @@ Both maps are cleared together when a session is explicitly reset (`bridge:reset
| **opencode** | `native` | `POST /session/:id/summarize` (server-side) |
| **claude** | `native` | `/compact` slash command via the Agent SDK → `compact_boundary` event |
| **plugins** | `native` | plugin bridge `compact()` (local summary prompt) |
| **CrewCoder (advertised extension)** | `native` | ACP `session/compact`; durable session is rewritten in place and its returned summary replaces only CrewCode's replay shard |
| **ollama / openrouter** (HTTP_ONLY) | `local-summary` | `LOCAL_COMPACT_PROMPT` + `compactLocalConversation` replaces our owned replay history |
| **pi / hermes / CrewCoder** | `summary-reset` | no native RPC → the agent summarizes its own live context, then we seed a fresh session with it (below) |
| **pi / hermes / older CrewCoder** | `summary-reset` | no advertised native RPC → CrewCode summarizes the bounded transcript, then seeds a fresh session (below) |
| _any provider with no thread/conversation key_ | `unsupported` | nowhere to persist a summary; reported instead of faked |

### `summary-reset` flow (pi / hermes / CrewCoder)
### CrewCoder native compact flow

CrewCode exposes `compact()` on the CrewCoder bridge only after observing the
exact `initialize._meta["crewcoder/sessionCompact"]` method advertisement. An
idle `/compact` calls `session/compact` with the current durable session id.
CrewCoder owns summary generation and the durable transcript rewrite, returns
the installed summary, and emits authoritative `_crewcoder/compaction_update`
progress. CrewCode replaces its local replay shard with `[continue, summary]`
and appends a visible compact-summary card, but keeps the full rich display
transcript, provider session id, and live bridge. If CrewCoder reports a skipped
small-session compact, CrewCode leaves replay and usage state unchanged.

### `summary-reset` flow (pi / hermes / older CrewCoder)

Native-session providers keep their context server-side and expose no compaction RPC, so we cannot shrink it directly. Instead:

Expand All @@ -81,7 +94,7 @@ Native-session providers keep their context server-side and expose no compaction
3. The bridge is torn down via the **idle-stop path** (`idle_stopped` → renderer drops its keys silently, no "agent exited" noise). Teardown + the `completed` event are deferred to a `queueMicrotask` so ordering stays `turn_end → completed → idle_stopped` and the bridge is never stopped re-entrantly from inside its own event.
4. The **next prompt** calls `bridge:start` with no resume id but local history present → `injectHistoryOnNextPrompt` re-arms → the summary is injected as `<conversation_history>` into a fresh, small upstream session.

> History note: previously every provider without a native `compact()` fell through to `prompt('/compact')`. Codex/HTTP-only/plugins worked, but pi/hermes/opencode/claude received the literal string `/compact`, which the agent simply answered. opencode and claude now compact natively; pi/hermes/CrewCoder use summary-reset.
> History note: previously every provider without a native `compact()` fell through to `prompt('/compact')`. Codex/HTTP-only/plugins worked, but pi/hermes/opencode/claude received the literal string `/compact`, which the agent simply answered. OpenCode and Claude now compact natively; pi, Hermes, and CrewCoder versions without the advertised extension use summary-reset.

## Visible chat transcripts (separate from replay history)

Expand Down
30 changes: 20 additions & 10 deletions docs/crewcoder-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,25 @@ plan is a normal composer message; CrewCoder treats that as a new

The bridge performs this handshake before reporting ready:

1. `initialize` with protocol version 1 and text-file capabilities.
1. `initialize` with protocol version 1 and text-file capabilities. The bridge
recognizes the exact `_meta["crewcoder/sessionCompact"].method ===
"session/compact"` advertisement; it does not assume the extension exists.
2. `session/load` when CrewCode has a saved native session id; unknown ids fall
back to `session/new`.
3. `session/set_external_directories` with CrewCode's complete session grant list, including `[]`
when all grants were removed.
4. `session/set_model` when a model is selected.
5. `session/set_reasoning_effort` applies CrewCode's selected effort to CrewCoder's provider client.
6. `session/prompt` runs each turn; `session/follow_up` queues an instruction into an active CrewCoder turn, and `session/cancel` is an ACP notification.
7. An idle `/compact` calls advertised `session/compact` with the durable
`sessionId`. Older CrewCoder versions without the advertisement keep the
existing CrewCode summary-reset fallback.

CrewCoder transcript replay contains user/assistant text only. When CrewCode's
richer local transcript exists, provider replay is suppressed. CrewCoder remains
a native-resume provider and uses summary-reset for manual compaction because it
has no native compact RPC.
a native-resume provider. Its advertised compact RPC rewrites that durable
session in place, so CrewCode must not clear the native session id, stop the
bridge, or seed a replacement session after a successful native compact.

## Event mapping

Expand All @@ -105,13 +111,17 @@ has no native compact RPC.
CrewCoder's compaction update is an additive namespaced ACP extension carrying
started/completed/failed status, automatic intent, progress, and a human-readable
message. The bridge treats it as authoritative and does not also infer
compaction from the later context-token drop. The compacted summary remains in
CrewCoder's durable session and is not copied into CrewCode's transcript.
CrewCode deliberately retains the full visible transcript as history; it is not
the provider context. On authoritative completion, CrewCode clears the stale
live context occupancy from memory, disk, and the latest visible usage strip
without fabricating `0` tokens. The next CrewCoder usage report repopulates the
meter with the compacted context's measured size.
compaction from the later context-token drop. Automatic updates omit the summary
body; the compacted summary remains only in CrewCoder's durable session.
Host-requested `session/compact` returns the authoritative summary and includes
it on the completed update. CrewCode replaces only its provider replay shard
with that summary and appends the visible compact-summary card; it deliberately
retains the full rich chat transcript as display history. A skipped update does
not reset context usage. After an applied completion, CrewCode clears stale live
context occupancy from memory, disk, and the latest visible usage strip without
fabricating `0` tokens. The next CrewCoder usage report repopulates the meter
with the compacted context's measured size. Idle compact progress must not
fabricate a model `turn_start`.

CrewCoder emits genuine reasoning, so the Hermes cosmetic-thinking filter must
not be applied. Gated tools are announced as pending before the permission
Expand Down
Loading
Loading