Skip to content

Commit 24a4fb5

Browse files
Add a CLAUDE.md
This is based on having asked Claude to go through comments left by Simon and I in all the PRs on the specification repo; hopefully this has extracted a good amount of the team's unwritten opinions and knowledge about how the spec should be structured. I've then tweaked it a fair bit myself, but it's still very much Claude output that we should refine and expand over time. The context for writing this was that Matt O got Claude to write a spec PR [1] for a new channel param, and was promptly told that it didn't belong in the spec nor should the spec be specifying tests. This led him to rightly not be very impressed by learning about the existence of a bunch of rules that had never been written down anywhere, and suggested that we write them down; thus this commit. It also led to a broader conversation about feature discoverability and testing; see [2]. The relevant parts of that conversation ("some stuff doesn't belong in the spec but should be tracked for inclusion in these upcoming things") have been included in the CLAUDE.md to guide people towards the right place for ensuring that a new feature gets included in these upcoming things even if it turns out it doesn't belong in the spec. I've focussed this CLAUDE.md on how to write specification points, as opposed to describing the build system for this repo, which most people who make spec changes never touch. [1] #433 [2] https://ably-real-time.slack.com/archives/CURL4U2FP/p1776169126491229
1 parent 70a6ffa commit 24a4fb5

1 file changed

Lines changed: 92 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## What This Is
6+
7+
The Ably features specification — the authoritative, language-agnostic description of how Ably SDKs must behave. Consumed by SDK developers across all Ably SDK repositories (pub/sub, chat, objects).
8+
9+
## Files You'll Edit
10+
11+
The spec lives in `specifications/`:
12+
13+
- `features.md` — REST/Realtime spec; the main file.
14+
- `chat-features.md` — Chat SDK spec.
15+
- `objects-features.md` — LiveObjects spec.
16+
- `api-docstrings.md` — language-agnostic docstrings that SDKs lightly edit and add to their code in order to support autocomplete and generate HTML documentation.
17+
- `protocol.md`, `encryption.md`, `test-api.md`, `feature-prioritisation.md`, `index.md` — supporting docs, rarely edited.
18+
19+
## Previewing Locally
20+
21+
```sh
22+
cd build
23+
npm install # once per clone
24+
npm run build # regenerate public/
25+
open public/index.html
26+
```
27+
28+
Hugo must be installed separately. There is no dev server — rebuild after edits.
29+
30+
## Spec Points — The Core Convention
31+
32+
Spec items are the unit of meaning in this repo. They look like this in Markdown:
33+
34+
```
35+
- `(RTN1)` Top-level behaviour.
36+
- `(RTN1a)` Subclause detail.
37+
```
38+
39+
The ID pattern is a letter prefix + integer + optional lowercase/number suffixes (e.g. `RTN1`, `REC2c6`, `CHA-V1`, `RSH3a2b`). These IDs are referenced from every SDK's source code and test suite, so **they are effectively a public API**.
40+
41+
See [`CONTRIBUTING.md` § Features Spec Points](CONTRIBUTING.md#features-spec-points) for the conventions around adding, modifying, removing, replacing, and deprecating spec items — read it before editing.
42+
43+
`npm run lint` enforces uniqueness of IDs across `features.md`, `chat-features.md`, `objects-features.md`. Duplicates typically arise from concurrent PRs being merged — when resolving, rename the later addition to the next available ID.
44+
45+
## Writing Principles
46+
47+
These principles are a WIP distilled from review comments left on the spec by Lawrence and Simon. Given this provenance, they skew towards things _not_ to do; more positive principles will be added over time.
48+
49+
### Scope
50+
51+
- Specify what SDKs must do, not what the server does. If a clause doesn't impose a requirement on an SDK, it doesn't belong here, even as "informational". For example, the `remainPresentFor` transport param, which specifies the duration that the server should wait before emitting a `leave` event after an abrupt disconnection, is a purely server-side behaviour (the client's only job in enabling this feature is to ensure that it sends the transport params that the user passes) and thus should not be mentioned in the spec.
52+
- Keep the spec self-contained. Don't tell the reader to consult another SDK's source code to understand a clause.
53+
- Don't prescribe tests ("A test should exist that…"). State the requirement; let implementers decide how to verify it.
54+
55+
### Precision
56+
57+
The general principle is to reduce ambiguity as much as possible for implementers, to maximise consistency between implementations. Here are some concrete examples.
58+
59+
- Use RFC 2119 keywords precisely. The preamble of `features.md` and `chat-features.md` declares that the keywords carry their RFC 2119 meaning whether lowercase or uppercase, and existing text is overwhelmingly lowercase — match the surrounding style. Avoid "will" (ambiguous between requirement and consequence) and "can" (not an RFC 2119 keyword — use "may").
60+
- Define every term you introduce. For example, don't say "retry the detachment cycle after a short pause" unless it's very clear from context what a "detachment cycle" means.
61+
- Be concrete. For example, no "a short pause" — give a duration.
62+
- When specifying a sequence of actions that the SDK must perform, make it clear whether the order in which they are performed matters.
63+
- Defer to other standards where possible; for example, when specifying how to percent-encode URL path variables, reference the rules and procedures of RFC 3986.
64+
65+
### Errors
66+
67+
- Whenever the specification states that the SDK must create an `ErrorInfo` (whether to throw it or to populate a `reason`), it must be explicit about which `code` and `statusCode` to use.
68+
- When choosing a `code`, look for the most appropriate error code in `errors.json` in the `ably-common` repository. If you haven't been told where to find a local copy of this repository, ask the user. If you can not find an appropriate error code, ask the user how to proceed.
69+
- When choosing a `statusCode`, try to proceed by analogy with other similar errors. Explain your logic to the user and ask them for clarification if the correct `statusCode` is unclear. (TODO: This is a bit hand-wavey because I — Lawrence — don't have a great sense of our rules for choosing status codes and often end up just choosing by analogy. But I imagine we can offer Claude better rules here.)
70+
71+
### Structure
72+
73+
- DRY via cross-reference. If a rule applies in two places, define it once and reference it.
74+
- TODO make sure we're covering the rules re updating docstrings and IDL; double-check the CONTRIBUING.md section to make sure it includes IDL too, and link to it
75+
- Rationale ("why") belongs in a design record, not in the normative clause.
76+
- Overview clauses whose rules are given by subclauses should be marked non-normative so readers don't implement the summary.
77+
- If there exists some invariant that the SDK maintains (for example, that internal property `foo` is non-nil if and only if internal property `bar` has a specific value), then use a non-normative clause to explain the existence of this invariant, and normative clauses to explain the behaviours that the SDK needs to perform in order to maintain this invariant.
78+
79+
### Exceptions to rules
80+
81+
- We sometimes bend the rules about immutability of specification points. In particular, if a spec point (or an entire spec document) is very new or has been implemented by a small (possibly zero) number of SDKs, then we may just modify or delete spec points without adding mutation markers in order to reduce spec point churn, and fix up the references in the affected SDKs. If you're unsure about whether it's OK to bend the rules for a given modification, ask the user.
82+
83+
## Future direction: Universal Test Suite and feature discoverability
84+
85+
This section describes an intention for how the specification will evolve in the future, and what considerations should be made when adding new features in order to track the work needed for this future direction.
86+
87+
The intention is that the following will exist:
88+
89+
1. A _Universal Test Suite_ (UTS): a pseudo-code set of tests that we intend to use LLMs to port to all of our SDKs
90+
2. A _feature discoverability mechanism_: an authoritative list of all Ably features, where a _feature_ is some behaviour that a client SDK is able to provoke, even if the SDK's only role is to relay a request that triggers behaviour on the server; a representative example is the aforementioned `remainPresentFor` transport param
91+
92+
As mentioned in the "Scope" section above, features that do not require any specific behaviour from a client SDK do not currently belong in the specification. However, when adding a new feature, if it becomes clear that the feature requires no new specification points, a sub-issue should be added to the Jira issue [PUB-3652](https://ably.atlassian.net/browse/PUB-3652), to ensure that, once the UTS and feature discoverability mechanism exist, this feature is covered by both. The title of the issue should be "Add non-spec feature to UTS and discoverability: <feature name>", e.g. "Add non-spec feature to UTS and discoverability: remainPresentFor".

0 commit comments

Comments
 (0)