Skip to content

feat: workspace owners can permanently delete a channel - #257

Open
sercada wants to merge 1 commit into
openclaw:mainfrom
sercada:feat/delete-channels
Open

sercada wants to merge 1 commit into
openclaw:mainfrom
sercada:feat/delete-channels

Conversation

@sercada

@sercada sercada commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor
Maintainer edits

MUST: Keep Allow edits from maintainers enabled for this PR so maintainers
can help update the branch when needed.

What Problem This Solves

Workspace owners can archive a channel but cannot remove a channel they no longer
want, together with its messages and files.

User Impact

User impact: owners can delete a channel from Channel settings → Delete
channel...
, from the API, or with clickclack channels delete. The dialog
shows what will be removed (messages, thread replies, pins, topics, files and
their size), offers to archive instead, and enables deletion only after the
channel name is typed. Deletion is permanent. People viewing the channel are
moved to their fallback conversation with a notice. The server refuses to
delete a workspace's last channel and the Guests workspace's provisioned
channels. On SQLite, two new migrations make deleting many messages fast: a
10k-message channel in a 120k-message workspace now deletes in 0.3 s instead of
6.6 minutes. Existing workspace deletion benefits the same way.

Why This Change Was Made

  • Deletion reuses the existing foreign-key cascade in one transaction, so the
    channel, messages, replies, reactions, pins, channel topics, read pointers,
    and notification settings go together. Uploads attached only to that channel
    are removed and their objects go through the durable cleanup queue already
    used for workspace deletion; uploads still used elsewhere and the workspace
    icon are kept. The audit log records the channel and the removed counts.
  • On SQLite, every row removed by the cascade did two full scans: one of
    messages to find replies and quotes (parent_message_id and
    quoted_message_id had no index), and one of the FTS5 search index, because
    the delete trigger matched the unindexed messages_fts.message_id. Deleting
    a channel therefore grew with channel size × workspace size. New partial
    indexes cover the child keys on both stores, and message_search_rows records
    each message's FTS rowid so the search triggers update rows by rowid. Both
    are needed; either alone leaves most of the cost.
  • A workspace-scoped channel.deleted event tells clients to leave the channel.
    Earlier events for the channel stay in the log, so replay cursors remain valid;
    realtime delivery already skips events whose channel no longer exists.
  • On PostgreSQL, a deletion locks the workspace row (FOR NO KEY UPDATE) before
    it counts or selects anything, in the same workspace-first order as workspace
    deletion and updates. Competing deletions cannot both pass the last-channel
    check, and the workspace icon cannot move onto an upload being removed; event
    appends and inserts, which take KEY SHARE, are not blocked. Candidate uploads
    are then locked FOR UPDATE and re-checked, so an attachment elsewhere either
    commits first (and the upload is kept) or waits and fails its foreign key.
  • Only human owners can delete. Moderators, members, and bot tokens get 403;
    blocked deletions return 409 with a blocker code the web app explains.
  • clickclack channels delete deletes only a channel named with --channel on
    its own command line (global or subcommand form). CLICKCLACK_CHANNEL and the
    saved default channel pick the channel for everyday commands, so they never
    choose what gets deleted. Without --yes the command prints the counts and
    exits.

The new migrations (sqlite/0043, sqlite/0044, postgres/0036) share numbers
with the agent question migrations in #258. Migrations apply by file name, so both
work together; whichever PR lands second can renumber to keep the sequence tidy.

Evidence

Settings danger zone Confirmation with preview Another member when it is deleted
settings confirm watcher

The CLI with a default channel in the environment, real server and CLI from
the same build:

Previous head `aa459dd5`: channels delete --yes deleted #launch from CLICKCLACK_CHANNEL
# previous-head-aa459dd5: workspace with #launch and #old-launch (2 messages); the shell exports CLICKCLACK_CHANNEL=launch
channels: launch old-launch
$ clickclack channels delete --yes
  deleted #launch: 0 messages, 0 thread replies, 0 files
  exit=0
channels: old-launch
$ clickclack channels delete --channel old-launch
  cannot delete #old-launch: 2 messages, 0 thread replies, 0 files (last_channel)
  exit=1
$ clickclack channels delete --channel old-launch --yes
  cannot delete #old-launch: 2 messages, 0 thread replies, 0 files (last_channel)
  exit=1
channels: old-launch
This head: the default channel is ignored; the named channel is deleted after the preview
# branch: workspace with #launch and #old-launch (2 messages); the shell exports CLICKCLACK_CHANNEL=launch
channels: launch old-launch
$ clickclack channels delete --yes
  usage: clickclack channels delete --channel CHANNEL --yes
  exit=1
channels: launch old-launch
$ clickclack channels delete --channel old-launch
  refusing to permanently delete #old-launch: 2 messages, 0 thread replies, 0 files without --yes
  exit=1
$ clickclack channels delete --channel old-launch --yes
  deleted #old-launch: 2 messages, 0 thread replies, 0 files
  exit=0
channels: launch

Tests:

  • Shared store suite on SQLite and Postgres (channeldeletiontest): the
    channel's messages, topics, search results, and exclusive upload are removed
    while other channels, shared uploads, and the workspace icon survive; the
    deletion counts match the preview; a replay cursor pointing at one of the
    channel's old events still replays forward to channel.deleted; guard rails
    for the last channel, provisioned Guests channels, archived channels, and
    non-owners.
  • TestCascadeChildKeysUseIndexes (SQLite query plan) and
    TestCascadeChildKeyIndexesExist (Postgres).
  • PostgreSQL interleavings, held open with real locks instead of timing:
    TestDeleteChannelSerializesLastChannelDecisions runs two deletions of a
    workspace's last two channels (one succeeds, one gets last_channel), and
    TestDeleteChannelKeepsUploadsAttachedDuringDeletion attaches the channel's
    only upload elsewhere while the deletion is paused after choosing it (the
    attachment either keeps the upload or fails). Both pass three times in a row;
    against the previous revision they fail with deleted=2 blocked=0 remaining=0
    and attachment succeeded but kept 0 rows.
  • TestSearchTriggersFindRowsThroughTheRecordedRowid: upgrades a database with
    an existing message, detaches the search rows from their message IDs, then
    edits one message and deletes the other's channel; both rows are still
    replaced or removed and search returns the edited message. With the old
    message_id triggers it fails with detached rows = 2.
  • TestChannelDeletionHTTP: 403 for members and bot tokens, 404 for
    unknown or already deleted channels, 204 for the owner, the live and
    replayed channel.deleted event on a member's socket, the audit entry, and
    the last_channel blocker with 409.
  • TestChannelsDeleteRequiresExplicitConfirmation: the CLI prints the preview
    and refuses without --yes.
  • TestChannelsDeleteIgnoresDefaultChannels runs the CLI entry point with
    CLICKCLACK_CHANNEL, then with a saved default channel: channels delete --yes
    sends no DELETE, while --channel in either flag position deletes. Without the
    fix it fails with CLICKCLACK_CHANNEL chose the channel to delete.
  • tests/e2e/channel-deletion.spec.ts: an owner deletes after reviewing the
    preview and typing the name; a member watching the channel is moved out with
    a notice; the last channel cannot be deleted.
  • apps/web/src/lib/channel-deletion.test.ts: name confirmation, blocker
    messages, and the notice text.
  • Local CI steps: pnpm fmt:check, pnpm lint, pnpm typecheck,
    pnpm -r typecheck, web unit tests, pnpm docs:site, and go test ./...
    with CLICKCLACK_POSTGRES_TEST_DSN, deadcode, and the embedded build is
    current and repeatable (coverage gate 86.8%). On this machine these tests also
    fail on unchanged main: TestHTTPBodyDeadlineStillBoundsStalledRequestBodies,
    uploadstore TestR2HeaderNetworkLifecycle/progressing_PUT, and intermittently
    TestHTTPErrorPathsAndSPA (1 of 4 runs on main), and
    TestHTTPSlashCommandRequiresChannelWriteAuthorityBeforeCallback (1 of 5 runs
    on main, 5 of 5 pass on this branch). The first CI run's Playwright job
    failed once in chat.spec.ts › clicking the active conversation does not refetch its messages; locally that test passes 3 of 3 alone and the whole
    chat.spec.ts plus channel-deletion.spec.ts pass 42 of 42 with two workers.

Deleting a channel on SQLite (Python sqlite3 3.45 applying the real
migrations; 120,000 messages in 12 channels; the deleted channel has 7,000
roots, 2,500 thread replies, and 500 quote replies):

Schema Delete time
main 395.4 s
child-key indexes only 220.3 s
this PR (indexes and search row map) 0.29 s

Applying this PR's migrations to that populated database took 0.14 s. A
smaller run (30,000 messages, 3,000 deleted) shows the two fixes are
independent: 27.7 s on main, 11.5 s with only the search row map, 17.7 s with
only the indexes, and 0.10 s with both.

AI-assisted: prepared with Claude Code; I reviewed the change and the evidence.

🤖 Generated with Claude Code

@sercada
sercada requested a review from a team as a code owner September 13, 2026 12:33
@clawsweeper

clawsweeper Bot commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Sep 13, 2026
@clawsweeper

clawsweeper Bot commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge.

What this changes

This PR adds permanent channel deletion for human workspace owners through the browser, API, SDK, and CLI.

Example: An owner removes #asia-sales, containing 4 messages and one 13 KB exclusive file.

  • Before: Archiving hides the channel while retaining its history and file.
  • After: The owner reviews the preview and types asia-sales to permanently delete it; connected main-app viewers move to another conversation with a notice.

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) The basic shipped flow has credible evidence, but three client defects, incomplete compatibility evidence, and unresolved product direction prevent merge readiness.
Proof confidence 🦐 gold shrimp (3/6) Real behavior proof is necessary before merge. See Before merge.
Patch quality 🦪 silver shellfish (2/6) Security review found an item that needs attention.

Product

Kind: Feature · Worth it: Needs a maintainer decision · Fix scope: Complete
User problem: Owners can archive unwanted channels but cannot remove their retained history and exclusive files.
Reason: The capability has clear value, but permanent retention changes, a new stored table, and public deletion contracts need owner direction.

Merge readiness

⛔ Blocked before merge - 10 items remain

Keep this PR open: permanent channel deletion remains absent from current main, and the contribution has distinct value, but three previously reported client defects remain.

Priority: P2
Reviewed head: c6d1ef841098ed1874b460bde5e5ba62fe0568d1
Owner decision: Required. See Decision needed.

Decision needed

  • Question: Should ClickClack expose human-owner-only permanent channel deletion, including exclusive-file removal and new API, SDK, event, and storage contracts?
  • Recommendation: Approve permanent deletion: Accept removal of unwanted channel history and exclusive files while retaining archive as the reversible alternative.
  • Why: This changes retention policy and introduces a public capability; existing archive and owner-permission decisions do not approve it, and no written approval appears on this PR.

Before merge

  • Add real behavior proof - Authority-chain proof required: inspected browser screenshots and the real-server CLI transcript demonstrate preview, confirmation, deletion, and main-app fallback; supplied HTTP tests support member/bot denial, but add recorded moderator and reassigned-owner rejection through the production deletion owners, verifying no row deletion, cleanup enqueue, or file-object removal, with sensitive values redacted. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Retire pending channel-list reads before removing the channel (P2) - A channel-list refresh can capture #doomed before deletion and return after this filter runs. Because channelsLoadSerial is unchanged, loadChannels accepts the response at lines 1087–1088 and restores the deleted sidebar entry. Invalidate or reconcile pending list responses when applying deletion. This previously reported defect remains on the same reviewed head.
  • Prevent pending searches from restoring deleted channel content (P2) - Start a search in #doomed, navigate to another conversation while the search or next-page response is pending, and delete #doomed. Navigation preserves an ordinary search session, and this handler filters only results already present without retiring searchRequestID. The delayed response at lines 2856–2857 or 2885–2889 restores deleted snippets and links. Reconcile or retire pending search responses during deletion. This previously reported defect remains unfixed.
  • Handle channel deletion in embedded conversation views (P2) - Deleting a channel emits channel.deleted without individual message-deletion events, but the new handler runs only in ChatApp. EmbedChannelView ignores this event, and EmbedThreadView delegates to a controller whose membership check excludes it. An already-open channel or thread embed keeps deleted history and an active composer until another operation fails. Handle deletion in both embedded views, retire their pending reads, and show a terminal deleted state. This previously reported defect remains unfixed.
  • Resolve security review attention item - No concrete authorization bypass or supply-chain regression was found, but destructive-authority final-effect evidence remains incomplete.
  • Resolve merge risk - Demonstrate that a moderator and a former owner whose ownership transfer completes before deletion authorization cannot remove channel rows, create cleanup jobs, or delete file objects.
  • Complete next step - Resolve the reported merge conflict against current main, preserving the owner-only channel settings behavior from fix: moderators get channel settings that fail with a database error #256 and refreshing affected generated assets.
  • Improve patch quality - Add final-effect proof for a moderator and prove ownership reassignment before deletion authorization prevents database and file removal.
  • Resolve maintainer decision - Resolve the maintainer decision shown above before merge.
  • Add data-model compatibility proof - The review found that existing stored data may not work after upgrade. Show that existing data still loads and works with this change.

Findings

  • [P2] Retire pending channel-list reads before removing the channel — apps/web/src/ChatApp.svelte:594-598
  • [P2] Prevent pending searches from restoring deleted channel content — apps/web/src/ChatApp.svelte:600-605
  • [P2] Handle channel deletion in embedded conversation views — apps/web/src/ChatApp.svelte:3327-3330

Tests

  • Low-value test apps/web/src/lib/channel-deletion.test.ts: Remove the notice-string and blocker-wording helper assertions: they pin incidental copy and mirror string branches; retain the exact-name safety cases and browser behavior coverage.
  • Missing end-to-end proof: Add shipped-server evidence for populated v0.7.0 upgrades on both backends and final-effect authorization rejection; browser coverage also needs delayed list/search responses and open embeds, with regressions failing before their repairs.
Agent review details

How this fits together

Browser, SDK, and CLI requests enter authenticated HTTP handlers; SQL transactions remove channel-owned rows, enqueue exclusive-file cleanup, and publish a workspace deletion event to clients.

flowchart LR
  A[Browser SDK and CLI] --> B[Authenticated HTTP API]
  B --> C[Owner authorized transaction]
  C --> D[SQLite or PostgreSQL]
  C --> E[Durable upload cleanup]
  E --> F[File storage]
  C --> G[Realtime clients]
Loading

Technical review

Best possible solution:

Land an owner-approved deletion capability that retires stale reads across main and embedded clients and preserves retained data during supported upgrades.

Do we have a high-confidence way to reproduce the issue?

This requests a new capability; source inspection confirms archive-only current-main behavior, and the introduced client defects are traceable in source without executing target code.

Is this the best way to solve the issue?

Transactional cascades, exclusive-upload rechecks, explicit CLI targeting, and archive-as-an-alternative fit the request, but deletion must retire pending reads and reach every conversation client.

Full review comments:

  • [P2] Retire pending channel-list reads before removing the channel — apps/web/src/ChatApp.svelte:594-598
    A channel-list refresh can capture #doomed before deletion and return after this filter runs. Because channelsLoadSerial is unchanged, loadChannels accepts the response at lines 1087–1088 and restores the deleted sidebar entry. Invalidate or reconcile pending list responses when applying deletion. This previously reported defect remains on the same reviewed head.
    Confidence: 0.99
  • [P2] Prevent pending searches from restoring deleted channel content — apps/web/src/ChatApp.svelte:600-605
    Start a search in #doomed, navigate to another conversation while the search or next-page response is pending, and delete #doomed. Navigation preserves an ordinary search session, and this handler filters only results already present without retiring searchRequestID. The delayed response at lines 2856–2857 or 2885–2889 restores deleted snippets and links. Reconcile or retire pending search responses during deletion. This previously reported defect remains unfixed.
    Confidence: 0.98
  • [P2] Handle channel deletion in embedded conversation views — apps/web/src/ChatApp.svelte:3327-3330
    Deleting a channel emits channel.deleted without individual message-deletion events, but the new handler runs only in ChatApp. EmbedChannelView ignores this event, and EmbedThreadView delegates to a controller whose membership check excludes it. An already-open channel or thread embed keeps deleted history and an active composer until another operation fails. Handle deletion in both embedded views, retire their pending reads, and show a terminal deleted state. This previously reported defect remains unfixed.
    Confidence: 0.99

Overall correctness: patch is incorrect
Overall confidence: 0.98

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against e9938a42620d.

Merge-risk options

Maintainer options:

  1. Hold merge for final-effect authorization evidence (recommended)
    Supply a production-path trace for moderator rejection and ownership reassignment, verifying channel data and exclusive file objects remain intact and no cleanup job is created.

Provenance checked

  • SQLite FTS synchronization changes intended behavior with a stated reason (cff5fb0: Migration 0033 scopes search by workspace inside FTS and keeps ordinary-message rows synchronized; the PR explains replacing message-ID scans with recorded rowid lookups to accelerate cascades.)
  • Archive and restore controls keeps the original intent (fix: add channel archive controls for managers #153: The prior change exposed reversible archival while preserving history; the new deletion dialog retains archive as the reversible alternative.)
  • Message hard-delete documentation changes intended behavior with a stated reason (2450cc5: The documented soft-delete contract preserves message sequence cursors; this PR explains why whole-channel removal is different while retaining earlier event cursors.)
  • Composer notice lifecycle keeps the original intent (ad89e31: Command dispatch retires stale conversation results and notices; the PR keeps dispatch-generation invalidation and carries a deletion notice into the fallback conversation.)
  • Embedded generated assets keeps the original intent (fix(build): preserve generated JavaScript literal whitespace #255: The prior fix preserves generated JavaScript literal whitespace; this PR refreshes embedded assets without restoring the removed normalizer.)

Testing

Proof path: shipped entry point.

Security

Needs attention: No concrete authorization bypass or supply-chain regression was found, but destructive-authority final-effect evidence remains incomplete.

Evidence

What I checked:

  • Current main retains archive-only channel management: The default-branch router exposes PATCH and message routes but no channel DELETE or deletion-preview route; targeted searches of the store interface, protocol, browser, and workspace documentation found no equivalent permanent-deletion capability. (apps/api/internal/httpapi/server.go:245, e9938a42620d)
  • Verified PR introduction: The pinned introduction adds deletion handlers, transactional cleanup, SQL migrations, client controls, protocol declarations, and tests; these edits belong to this PR. (apps/api/internal/store/postgres/channel_deletion.go:35, c6d1ef841098)
  • Pending browser responses remain admissible: Deletion filters channels and existing search results without changing channelsLoadSerial or searchRequestID; list and search response handlers still admit earlier responses. (apps/web/src/ChatApp.svelte:594, c6d1ef841098)
  • Embedded views omit deletion handling: The channel embed handles message mutations, reactions, and channel.updated but ignores channel.deleted; the thread embed delegates to a controller that requires message or root identifiers absent from this event. (apps/web/src/components/embed/EmbedChannelView.svelte:372, c6d1ef841098)
  • Supplied visible behavior proof: Inspected the three downloaded screenshots linked in the PR body: channel settings, a preview showing 4 messages and one 13 KB file with incomplete confirmation disabled, and a member moved to #general with a deletion notice; the body also supplies a real-server CLI before/after transcript. (c6d1ef841098)
  • Authorization reaches transactional deletion: HTTP rejects bot tokens and passes the authenticated user ID to the store, which checks current owner membership before deleting rows and inserting cleanup records; supplied HTTP tests exercise owner success and member/bot rejection, but no deletion-specific moderator or ownership-transfer final-effect evidence is supplied. (apps/api/internal/httpapi/channels.go:140, c6d1ef841098)

Labels

Label changes:

  • add merge-risk: 🚨 security-boundary: Permanent row and file deletion introduces destructive owner authority whose nearest-forbidden and reassigned-owner final effects are not fully demonstrated.

Label justifications:

  • P2: This is a useful optional capability with limited client-state defects, rather than an urgent regression in an existing shipped workflow.
  • merge-risk: 🚨 compatibility: The patch adds a persistent search-row table, replaces SQLite search triggers, and introduces public deletion contracts without complete latest-stable upgrade evidence.
  • merge-risk: 🚨 session-state: Pending list/search responses and embedded views can retain or restore deleted channel state.
  • merge-risk: 🚨 security-boundary: Permanent row and file deletion introduces destructive owner authority whose nearest-forbidden and reassigned-owner final effects are not fully demonstrated.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦐 gold shrimp and patch quality is 🦪 silver shellfish.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only; repair and merge need explicit maintainer commands such as @clawsweeper autofix or @clawsweeper automerge.

History

Review history (26 earlier review cycles; latest 8 shown)
  • reviewed 2026-10-09T23:03:16.239Z sha c6d1ef8 :: blocked before merge. :: [P2] Retire pending channel-list reads before removing the channel | [P2] Prevent pending searches from restoring deleted channel content
  • reviewed 2026-10-10T11:02:25.846Z sha c6d1ef8 :: blocked before merge. :: [P2] Retire pending channel-list reads before removing the channel | [P2] Prevent pending searches from restoring deleted channel content
  • reviewed 2026-10-10T12:58:14.998Z sha c6d1ef8 :: blocked before merge. :: [P2] Retire pending channel-list reads before removing the channel | [P2] Prevent pending searches from restoring deleted channel content
  • reviewed 2026-10-10T14:49:03.459Z sha c6d1ef8 :: blocked before merge. :: [P2] Retire pending channel-list reads before removing the channel | [P2] Prevent pending searches from restoring deleted channel content
  • reviewed 2026-10-10T17:46:38.174Z sha c6d1ef8 :: blocked before merge. :: [P2] Retire pending channel-list reads before removing the channel | [P2] Prevent pending searches from restoring deleted channel content | [P2] Handle channel deletion in embedded conversation views
  • reviewed 2026-10-10T23:46:57.297Z sha c6d1ef8 :: blocked before merge. :: [P2] Retire pending channel-list reads before removing the channel | [P2] Prevent pending searches from restoring deleted channel content | [P2] Handle channel deletion in embedded conversation views
  • reviewed 2026-10-11T02:48:01.604Z sha c6d1ef8 :: blocked before merge. :: [P2] Retire pending channel-list reads before removing the channel | [P2] Prevent pending searches from restoring deleted channel content | [P2] Handle channel deletion in embedded conversation views
  • reviewed 2026-10-11T04:56:41.323Z sha c6d1ef8 :: needs real behavior proof before merge. :: [P2] Retire pending channel-list reads before removing the channel | [P2] Prevent pending searches from restoring deleted channel content | [P2] Handle channel deletion in embedded conversation views

Reviewed October 11, 2026, 10:31 AM ET / 14:31 UTC (Revision 27).

@sercada
sercada force-pushed the feat/delete-channels branch from b6d6079 to aa459dd Compare September 13, 2026 12:57
Owners delete a channel from Channel settings, the API, or the CLI after
reviewing what will be removed and typing the channel name. The channel's
messages, replies, reactions, pins, topics, read state, and exclusive uploads
go in one transaction; a workspace-scoped channel.deleted event moves viewers
out. The last channel and the Guests workspace's provisioned channels cannot
be deleted. The CLI deletes only a channel named with --channel on its command
line, never CLICKCLACK_CHANNEL or the saved default.

On SQLite, cascading many message deletions scanned both the messages table
and the FTS index once per row. Child-key indexes and a message-to-search-row
map make a 10k-message channel in a 120k-message workspace delete in 0.3 s
instead of 6.6 minutes, which also speeds up workspace deletion.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@sercada
sercada force-pushed the feat/delete-channels branch from aa459dd to c6d1ef8 Compare September 13, 2026 13:27
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. labels Sep 13, 2026
@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. merge-risk: 🚨 session-state 🚨 Merging this PR could lose, corrupt, stale, or mis-associate session or agent state. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Oct 8, 2026
@clawsweeper clawsweeper Bot added merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. and removed proof: sufficient Contributor real behavior proof is sufficient. labels Oct 11, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 session-state 🚨 Merging this PR could lose, corrupt, stale, or mis-associate session or agent state. P2 Normal priority bug or improvement with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant