# Design note — merging and splitting topics

**Dated 2026-08-05. Written before the code, per the provenance practice in
[ROADMAP.md](../../ROADMAP.md#proving-independence).**

---

## The job to be done

Two threads about the same thing. One thread that turned into two arguments.
Every forum grows both within a week of opening, and a moderator with neither
tool can only lock one and ask people to move — which nobody does.

## Decision 1 — the unit is the post, not the topic

Merging is "move these posts into that thread". Splitting is "move these posts
out of this one". They are the **same operation** with a different destination:
an existing topic, or a new one.

So one service, one code path, two entry points. A separate implementation for
each would be two chances to get the counters wrong.

## Decision 2 — order by when it was written, not by where it was

After a merge, posts are renumbered by `created_at` across the combined thread.

The alternative — appending one thread to the end of the other — produces a
conversation where somebody answers a question that has not been asked yet. The
timestamps are what make a merged thread readable, and they are already true.

## Decision 3 — a merged topic is deleted, not emptied

The source topic ends up with no posts, and a topic with no posts is not a
thing anybody should find. It is soft-deleted, like every other deletion here,
so a mistake is recoverable.

Its **followers move to the destination**. They followed a conversation, and
the conversation is still going on — just somewhere else. Dropping them would
punish people for a moderator's tidy-up.

## Decision 4 — the first post cannot be split out

A topic's first post *is* the topic: its title, its author, its date. Lifting
it out leaves a thread that starts mid-sentence.

Somebody who genuinely wants that wants a merge in the other direction, and the
interface says so rather than silently doing something surprising.

## Decision 5 — splitting makes a real topic, with a real author

The new thread's first post is the earliest post moved into it, and the topic's
author is **that post's author** — not the moderator who pressed the button.
The person who wrote it is who a reader needs to see.

The moderator's involvement belongs in the log, which is where it goes.

## Decision 6 — counters are recomputed, never adjusted

Every one of these moves posts between topics and topics between forums, and
every one of them is a chance to leave a count two out.

So nothing does arithmetic on a counter. Both affected topics and both affected
forums are **recounted from the rows** afterwards. It is more queries and it is
correct, and a forum listing that says "12 topics" over eleven rows is the kind
of thing people notice and never trust again.

## Decision 7 — both are logged, and neither is reversible

`mod_log` gets a row naming what happened to which topic, the same as every
other moderation action.

Neither can be undone in one step. The interface says so before it acts. A
merge that could be un-merged would need to remember which posts came from
where, which is a table serving one undo button.

## What this does not do

- **No merging into a topic in a forum somebody cannot see.** The destination
  is validated the same way a move is.
- **No partial merge.** All of the source's posts go, or none. "Merge some of
  it" is a split followed by a merge, and saying so is clearer than a mode.
- **No cross-site or cross-forum-type merges.** A topic goes to a topic.
- **No automatic redirect from the old topic.** It is soft-deleted; a moderator
  who wants a signpost can leave a reply saying where the conversation went.
