Files
openchamber/.agents/skills/changelog-authoring/SKILL.md
T
Bohdan Triapitsyn 3d2bcf7ed6 chore(changelog): retire CHANGELOG.md as a dependency
The update dialog (server and desktop) now reads changelog/index.json and
renders title, intro and groups; the release workflow builds the GitHub
Release body and name from changelog/<version>.md; oc-dev, the issue-intake
agent, AGENTS.md and the changelog skill no longer point at the file.

CHANGELOG.md stays as a legacy copy for installs up to 1.22.1, which fetch
it for update notes. The generator refreshes it while it exists and never
recreates it, so deleting it after 2026-09-19 retires it for good.

Generated outputs hold released versions only, so editing unreleased.md
never makes them stale: agents write that file and nothing else, and
oc-dev create-release does the generation.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 17:02:28 +03:00

9.0 KiB

name, description, license, compatibility
name description license compatibility
changelog-authoring Use only when the maintainer explicitly asks to update the changelog — then write `changelog/unreleased.md` (main app and VS Code extension) summarizing changes since the latest git tag. MIT opencode

Gate

The changelog is written once per release, by the maintainer, as one story. changelog/ stays untouched by every other task; a fix or a merged PR lands without a changelog line. Proceed only when the current message asks to update the changelog.

Write changelog/unreleased.md and nothing else. Generation is not your job: oc-dev create-release turns the file into changelog/<version>.md with the date and renders packages/vscode/CHANGELOG.md and changelog/index.json from it. Never run the generator or touch those files. bun run changelog:check only validates the shape of what you wrote and writes nothing; changelog/README.md describes the format.

unreleased.md opens with a title: front matter line (see The title) and holds two sections:

  • ## App — Web, Desktop, Mobile/PWA, shared UI.
  • ## VS Code — the extension only, written separately (see below).

The shape of a release

Every release section is grouped. Under the version header come, in this order and only when non-empty:

### New
- **VS Code: comments on code.** Select lines, click the `+` in the gutter ... (thanks to @felipegenef)
- Project actions in worktrees: a session in a worktree can use the parent project's saved actions (thanks to @mattv8).

### Improvements
- Chat: Markdown tables are readable again, columns take the width their content needs (thanks to @ChangeHow).

### Fixes
- Chat: huge patches in tool cards open without freezing the page (thanks to @karimodm).

### Misc
- Bundled OpenCode updated to 1.19.

Where a change goes:

  • New — something the user could not do before: a feature, a surface, a language.
  • Improvements — something they could do works better or reads clearer now.
  • Fixes — something was broken and showed a wrong result; the bullet names the symptom.
  • Misc — bundled tool versions, packaging, platform support, retirements. Rarely more than a few lines.

The generator emits the groups in this order whatever order the source lists them and drops empty ones; version, date, and headers are its concern, not yours.

The title

Every release carries a one-line title: in its front matter. The website lists it beside the version and uses it as the heading of the release page, so it is the one line most people read. It answers "what would a user remember this release for":

  • Two to six words naming the change most users will notice. For a fix-only patch, name what works again: Terminal works again on Windows, Faster session switching.
  • Plain words, sentence case; product names keep their casing. No area prefix with a colon, no trailing period, no version number, no credit.
  • Never a category alone (Fixes, Stability, Improvements, Polish) and never a bare area (Git, Chat): the title has to teach the reader something.
  • Two headliners at most, joined with and, and only when the release really has two.

oc-dev create-release refuses a release without a title. In unreleased.md it sits at the top:

---
title: Comments on code in VS Code
---

## App

The bullet

The reader is a user of the app. They never opened the code, they will not open the PR, and they give a bullet about five seconds. Write for that reader:

  • One sentence, two at most. A bold highlight may take three. Under about 200 characters for a regular bullet.
  • Name what they see or do. The screen, the button, the gesture, the outcome. When a fix removed a symptom, name the symptom in plain words ("froze the page", "sent the comment by accident", "stopped at the first page").
  • Plain words only. Anything a user would have to look up is out: store, cache, route, payload, reconcile, authoritative, lifecycle, runtime, listing, revision, PTY, bridge. Internal component names are out unless the user sees them on screen.
  • State the new behaviour directly. Say what happens now. Framing it against the old way ("X, not Y", "instead of Y", "rather than Y") is the tell of machine-written notes; drop the second half and let the sentence stand.
  • Area prefix, then the fact. Chat:, Settings/Providers:, Git:, Mobile:, Server:, CLI:, VS Code: in the main file. A highlight bolds its prefix: - **Project actions:** ....
  • Details stay in the PR. No commit hashes, file paths, numbers that do not change what the user does, or mechanism. One concrete number is fine when it is the whole point ("more than 200 sessions").

Worked example, same change:

Weak: a saved action counts as running exactly while its command runs. When the command exits, the stop icon goes away even if the terminal tab stays open, and a second client can start the action again. Every client shows the same run, and the sidebar marks a directory that has one. Sessions in a linked worktree can use the parent project's actions; they run in the worktree by default.

Good: the running state of a saved action is reliable now. It shows as running only while the command is really running, every device sees the same state, and the sidebar shows which project has something running. Worktrees can use the parent project's actions.

The weak version is accurate and lost the reader at the first comma. The good version keeps the three things a user notices and drops the mechanics that explain them.

Load .agents/skills/communication-style/SKILL.md and run its pattern scan over the finished sections; its rules on em dashes, hedging, and puffery apply here unchanged.

Gather

Determine the base and read everything through HEAD:

BASE=$(git describe --tags --abbrev=0 2>/dev/null || git rev-list --max-parents=0 HEAD)
git log --oneline "$BASE"..HEAD
git diff --stat "$BASE"..HEAD

A squashed merge (subject ending in (#123)) or a Merge pull request #123 commit hides the real change behind a terse subject. Read the PR: gh pr view <number> --json number,title,body,author,mergedAt. Distill its intent into the bullet shape above; the body's own wording is reviewer-facing and stays there. When gh cannot fetch it, use the commit and diff and say what remains uncertain.

Follow-ups fold in. A maintainer commit that completes or reworks a merged PR (a "complete ... follow-ups" commit, a reshaping merge) has no bullet of its own; its user-visible effect goes into the bullet of the PR it finished, written as one behaviour. A change with no user-visible effect (tooling, CI, tests, docs, dead-code removal, internal guards) gets no bullet at all.

Gathering is complete when every user-visible change has evidence, a known platform reach, and a contributor identity where one exists.

Order and highlights

  • Inside each group, sort by user impact: breaking changes, then what most users meet daily, then the rest, visual polish last.
  • Bold the prefix of the strongest one to three bullets in the whole release and put each at the top of its group. A highlight introduces a capability, changes a common workflow, or fixes something severe. Size of the diff and effort spent are not reasons to bold.
  • A change that is both a feature and a fix (a reworked area) gets one bullet in the group that describes what the user gains most; a second bullet only when the two halves are things a user would look for separately.
  • Rank each changelog on its own; a main-app highlight is not automatically a VS Code highlight.

VS Code section

An entry belongs here only when the extension actually mounts the surface: trace from packages/vscode/webview/main.tsxVSCodeAppVSCodeLayout, which mounts a subset of the shared UI, and read the surface map in packages/vscode/src/DOCUMENTATION.md. Server-side changes have no entry here; the extension runs no OpenChamber server. Prefixes drop the VS Code: part. Bullets are written separately from the App section rather than tagged, so reachability is a decision made per bullet. When reachability is uncertain, leave the entry out; a false entry becomes a bug report.

Credit

End the bullet with (thanks to @username) using the GitHub login from the PR or commit. The repo owner btriapitsyn gets no credit line.

Done when

Read each finished section top to bottom and check every bullet:

  • A user could point at it in the app within five seconds of reading it.
  • It is one or two sentences (three for a highlight) in plain words, with no mechanism and no contrast against the old behaviour.
  • It sits in the group its wording claims (a Fix names a symptom, a New names a capability) and no higher than the bullets above it in impact.
  • Empty groups are absent; present groups appear in the order New, Improvements, Fixes, Misc.
  • It appears only in the section whose runtime receives it.
  • Its contributor is credited.
  • The title: line names the release's headline change in two to six plain words.
  • bun run changelog:check passes; nothing else in the repo changed.