-
Notifications
You must be signed in to change notification settings - Fork 247
Add AGENTS.md: a 22-line agent entry point #3789
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # Jamulus — Agent Instructions | ||
|
|
||
| Jamulus is a real-time networked music jamming application (client and server). Qt/C++, built with qmake. Entry point: `src/main.cpp`; build variants via `CONFIG` flags in `Jamulus.pro`. | ||
|
|
||
| This file is the starting point for coding agents. It links to the detailed docs — read the relevant one before starting: | ||
|
|
||
| - [CONTRIBUTING.md](CONTRIBUTING.md) — process, code style, licensing, ownership. Its rules apply to agent-assisted work without exception. | ||
| - [COMPILING.md](COMPILING.md) — building on every supported platform. | ||
| - [DEPLOY.md](DEPLOY.md) — moving a self-built server binary onto production hosts and verifying it. | ||
| - [docs/JAMULUS_PROTOCOL.md](docs/JAMULUS_PROTOCOL.md) — the wire protocol. | ||
| - [SECURITY.md](SECURITY.md) — report vulnerabilities to team@jamulus.io, never in a public issue. | ||
|
|
||
| ## Scope | ||
|
|
||
| - One logical change per PR. No drive-by refactors, no reformatting of code you didn't otherwise touch, no bundled extras. | ||
| - Features must be agreed in a GitHub issue or Discussion **before** coding — see CONTRIBUTING.md. If no agreement exists, propose; don't implement. | ||
| - Stability outranks everything: Jamulus runs live performances. Prefer not adding a feature over adding risk (KISS principles in CONTRIBUTING.md). | ||
|
|
||
| ## Architecture laws | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer those to live somewhere else. I believe it's model specific...
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed — moved to a new docs/ARCHITECTURE.md, written for humans as well as agents: system overview, source map, threading model, and these invariants. AGENTS.md now carries only one-line summaries and a link. |
||
|
|
||
| Violating these causes audible failures for every connected musician, so they are non-negotiable: | ||
|
|
||
| 1. **Never block the real-time path.** The audio capture/playback callbacks (`src/sound/`) and the server's UDP receive → mix → send path (`socket.cpp`, `channel.cpp`, `server.cpp`) must not perform blocking I/O (DNS, HTTP, disk, database), wait on locks contended by non-real-time threads, or do unbounded allocation per packet. Slow work must run asynchronously on another thread; when its result isn't ready, the real-time path fails open and continues. A single synchronous lookup here freezes the audio of everyone on the server. | ||
| 2. **The wire protocol is a compatibility contract.** `protocol.cpp` must interoperate with every older client and server in the wild. Never renumber `PROTMESSID_*` values, never change the layout of an existing message — extend only by adding new message IDs. Read the header comment in `src/protocol.cpp` and [docs/JAMULUS_PROTOCOL.md](docs/JAMULUS_PROTOCOL.md) before touching it. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did this renumbering really happen?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not aware of this happening.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then remove it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed. |
||
| 3. **All network input is adversarial.** UDP packets arrive from arbitrary internet hosts. Bounds-check every length and count field before use. A malformed packet must be dropped silently — it must never crash, block, or corrupt the server. | ||
|
|
||
| ## DO NOT edit (generated or third-party) | ||
|
|
||
| - `moc_*.cpp`, `ui_*.h`, `qrc_*.cpp` are generated at build time (moc/uic/rcc) — never hand-edit. | ||
| - `*.qm` files are compiled translations — regenerate from the `.ts` sources in `src/translation/`, never hand-edit. | ||
| - `libs/` is third-party (opus, oboe, NSIS). `libs/oboe` is a git submodule — run `git submodule update --init` if it is empty. | ||
| - Never run clang-format on any of the above. | ||
|
|
||
| ## Build / verify | ||
|
|
||
| - Linux desktop: `qmake && make` (`qmake-qt5` on Fedora). | ||
| - Headless server: `qmake "CONFIG+=headless serveronly" && make`. | ||
| - macOS: `qmake QMAKE_APPLE_DEVICE_ARCHS=arm64 QT_ARCH=arm64 -spec macx-xcode Jamulus.pro` (use `x86_64` on Intel Macs; `macx-clang` to build with `make`), then `xcodebuild build` and `macdeployqt ./Release/Jamulus.app`. Full platform details: [COMPILING.md](COMPILING.md). | ||
| - There is no automated test suite. To verify a change: build a headless server and run `./Jamulus --server --nogui`, connect a client build to `127.0.0.1`, and exercise the changed behavior. State in the PR what you tested and on which platform. An untested change is an unfinished change. | ||
|
|
||
| ## Style (C / C++ / Obj-C++) | ||
|
|
||
| - Run `make clang_format` before committing (the target exists once `qmake` has generated the Makefile). CI enforces a specific clang-format version — see `clangFormatVersion` in `.github/workflows/coding-style-check.yml`. | ||
| - If you add a new source directory or file extension, update `.github/workflows/coding-style-check.yml` and `.clang-format-ignore` as well as `Jamulus.pro` (see the comment above `CLANG_FORMAT_SOURCES`) — otherwise CI and local formatting silently diverge. | ||
| - Rules in brief: 4-space indent (no tabs), braces on their own line, space inside `()` and around `if`/`for`/`while` conditions, column limit 150, left pointer alignment (`int* p`). | ||
| - New files need an AGPL 3.0 (or later) license header; pre-3.12.1 files carry combined GPL/AGPL blocks — leave existing headers alone. Details in CONTRIBUTING.md. | ||
|
|
||
| ## Translations | ||
|
|
||
| - Use substitution, never concatenation: `tr ( "Hello, %1!" ).arg ( name )` — concatenated fragments cannot be translated. | ||
| - Per-language `.ts` files live in `src/translation/`; see [docs/TRANSLATING.md](docs/TRANSLATING.md). | ||
|
|
||
| ## JSON-RPC | ||
|
|
||
| - If you change RPC methods, regenerate `docs/JSON-RPC.md` with `tools/generate_json_rpc_docs.py` — CI (`check-json-rpcs-docs.yml`) fails otherwise. | ||
|
|
||
| ## Other tooling | ||
|
|
||
| - `.sh` files: lint with `shellcheck --shell=bash` and `shfmt -d`. | ||
| - Python (under `tools/`): max line length 99, run `pylint` (< 3.0) with the repo's `.pylintrc`. | ||
| - ChangeLog: put `CHANGELOG: <one sentence>` in the PR description (`CHANGELOG: SKIP` for changes users won't notice). Do **not** edit the `ChangeLog` file — it causes conflicts. | ||
|
|
||
| ## Version / portability constraints | ||
|
|
||
| - Minimum Qt is **5.12.2**. Guard newer APIs with `#if QT_VERSION >= QT_VERSION_CHECK(...)`. | ||
| - Maintain C++11 compatibility and keep Windows, macOS, Linux, Android and iOS building. | ||
|
|
||
| ## PR expectations | ||
|
|
||
| - Naming your branch `autobuild/<name>` triggers CI builds of all targets on your fork — use it before opening the PR. | ||
| - Include the `CHANGELOG:` line, and for new dependencies or build changes add `AUTOBUILD: Please build all targets` to the PR description. | ||
| - PRs need two approving reviews to merge; the submitter is responsible for follow-up questions and agreed changes (see CONTRIBUTING.md). | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this needed? I don't think an agent should need to care about this.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,7 +66,19 @@ make | |
| sudo make install # optional | ||
| ``` | ||
|
|
||
| To control the server with systemd, runtime options and similar, refer to the [Server manual](https://jamulus.io/wiki/Server-Linux). | ||
| To control the server with systemd, runtime options and similar, refer to the [Server manual](https://jamulus.io/wiki/Server-Linux). If you plan to copy the binary onto other machines, read [DEPLOY.md](DEPLOY.md) first — architecture and library mismatches between build and target hosts are the most common cause of broken deployments. | ||
|
|
||
| ### Troubleshooting: moc errors with GCC 13+ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should fix this then.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. I can reproduce the failure on Ubuntu 24.04 (GCC 13.3 / Qt 5.15.13) and will open a separate PR that fixes it in the build itself. Once that merges, this section can shrink to a sentence or disappear.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update: I tried to reproduce this on clean main before writing a fix — Ubuntu 24.04, GCC 13.3, Qt 5.15.13, both |
||
|
|
||
| On distributions shipping GCC 13 or later (e.g. Ubuntu 24.04), Qt 5's `moc` can fail to parse the system headers because of the `_GLIBCXX_VISIBILITY` macro. Workaround — after `qmake`, generate `moc_predefs.h` and neutralize the macro, then build: | ||
|
|
||
| ```shell | ||
| make moc_predefs.h | ||
| printf "\n#undef _GLIBCXX_VISIBILITY\n#define _GLIBCXX_VISIBILITY(V)\n" >> moc_predefs.h | ||
| make | ||
| ``` | ||
|
|
||
| (If your Makefile builds into `release/`, the file is `release/moc_predefs.h` and is produced by `make -f Makefile.Release release/moc_predefs.h`.) | ||
|
|
||
| --- | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,8 @@ We’d really appreciate your support! Please ensure that you understand the fol | |
| - Otherwise, please [post on the GitHub Discussions](https://github.com/jamulussoftware/jamulus/discussions) and say that you are planning to do some coding and explain why. Then we can discuss the specification. | ||
| - Please begin coding only after we have agreed on a specification to avoid putting a lot of effort into something that may not be accepted later. | ||
|
|
||
| If you work with an AI coding agent, [AGENTS.md](AGENTS.md) is its entry point into this repository. Everything in this document applies to agent-assisted contributions without exception — you remain the author, and you are expected to understand and stand behind every line you submit. | ||
|
|
||
|
|
||
| ## Jamulus project/source code general principles | ||
|
|
||
|
|
@@ -39,7 +41,7 @@ Please see the [.clang_format file](https://github.com/jamulussoftware/jamulus/b | |
|
|
||
| - Insert a space before and after `(` and `)`. There should be no space between `)` and `;` or before an empty `()`. | ||
| - Enclose all bodies of `if`, `else`, `while`, `for`, etc. in braces `{` and `}` on separate lines. | ||
| - Do not use concatinations in strings with parameters. Instead use substitutions. **Do:** `QString ( tr ( "Hello, %1. Have a nice day!" ) ).arg( getName() )` **Don't:** `tr ( "Hello " ) + getName() + tr ( ". Have a nice day!" )` ...to make translation easier. | ||
| - Do not use concatenations in strings with parameters. Instead use substitutions. **Do:** `QString ( tr ( "Hello, %1. Have a nice day!" ) ).arg( getName() )` **Don't:** `tr ( "Hello " ) + getName() + tr ( ". Have a nice day!" )` ...to make translation easier. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Open a separate PR which only contains this typo fix. This will be a trivial merge
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done — #3792. |
||
|
|
||
| #### Python | ||
| Please install and use [pylint](https://pylint.org/) to scan any Python code. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # Deploying a Jamulus Server | ||
|
|
||
| [COMPILING.md](COMPILING.md) ends when the binary exists. This document covers the step after that: putting a self-built headless server binary on a production host and verifying it actually runs. Most self-inflicted server outages happen in this step, and every rule below corresponds to a real-world failure. | ||
|
|
||
| For configuring and operating a server (registration, recording, welcome message, etc.), see the [Server manual](https://jamulus.io/wiki/Running-a-Server). | ||
|
|
||
| ## Build for the target, not for the build machine | ||
|
|
||
| - **CPU architecture must match.** A binary built on x86-64 will not run on an ARM host (and vice versa) — the service crash-loops with `Exec format error`. Before copying, compare `file ./Jamulus` on the build machine with `uname -m` on the target. | ||
| - **Build on the oldest OS release you deploy to.** Binaries depend on the glibc/libstdc++ of the build machine. A binary built on Ubuntu 24.04 fails on 22.04 with `GLIBCXX_3.4.32 not found`, while a 22.04 build runs fine on 24.04 and later. Newer hosts run older binaries; the reverse never holds. | ||
| - **Check shared libraries after every copy.** `ldd /path/to/jamulus | grep "not found"` must print nothing. This catches a missing Qt runtime package before systemd shows you a crash loop. The minimal headless runtime needs the Qt core, network, concurrent and xml libraries (see [COMPILING.md](COMPILING.md)). | ||
| - **Low-memory hosts:** on machines with ≤ 1 GB RAM, build with `make -j1`, or build on a bigger machine of the same OS/architecture and copy the binary. If you must add temporary swap to survive a build, remove it afterwards — see below. | ||
|
|
||
| ## Run under systemd | ||
|
|
||
| Use the unit shipped in [`linux/debian/jamulus-headless.service`](linux/debian/jamulus-headless.service) as your starting point — it already encodes hard-won defaults (dedicated `jamulus` user, `Nice=-20`, real-time I/O scheduling, `MemorySwapMax=0`, `Restart=on-failure`). Manage the server only through `systemctl`; never kill the process by PID. | ||
|
|
||
| ## Host tuning | ||
|
|
||
| - **Enlarge the UDP receive buffer.** Under load, default kernel buffers drop packets, which musicians hear as dropouts. Set in `/etc/sysctl.d/99-jamulus.conf`: | ||
|
|
||
| ``` | ||
| net.core.rmem_max=4194304 | ||
| net.core.rmem_default=4194304 | ||
| ``` | ||
|
|
||
| - **No swap on a live server.** Swapping causes latency spikes audible to everyone connected. Keep swap off (the shipped systemd unit sets `MemorySwapMax=0` for the service; better still, don't enable swap on the host at all). | ||
| - **Don't compete with the audio process.** Never compile, or run other CPU-heavy work, on a host while musicians are connected — CPU contention causes dropouts just like network loss does. | ||
|
|
||
| ## Firewall | ||
|
|
||
| - Inbound UDP on the server port (default 22224) must be open. Remember that cloud providers filter *in front of* the host (AWS security groups, OCI security lists) in addition to any host firewall, and some images run `firewalld` by default — you may need to open the port in two places. | ||
| - If you enable JSON-RPC (`--jsonrpcport`), never expose that TCP port to the internet. Bind it to localhost or firewall it to specific trusted addresses, and always use `--jsonrpcsecretfile`. | ||
| - Corollary: a TCP probe of a firewalled port from outside proves nothing about the service. Verify RPC from an allowed host, not from the internet. | ||
|
|
||
| ## Verify every deploy | ||
|
|
||
| A deploy is finished when all of these pass on the target host — not when the file lands: | ||
|
|
||
| ```bash | ||
| file /usr/bin/jamulus-headless # architecture matches `uname -m` | ||
| ldd /usr/bin/jamulus-headless | grep "not found" # no output | ||
| /usr/bin/jamulus-headless --version # the version you just built | ||
| systemctl status jamulus-headless # active (running) | ||
| ``` | ||
|
|
||
| Then check the restart counter is stable (`systemctl show -p NRestarts jamulus-headless`, again a minute later — a crash loop can look "active" in a single snapshot), and finally do an end-to-end test: if the server is registered with a directory, confirm it appears in the listing, and connect a client to confirm audio passes. | ||
|
|
||
| When a change "isn't working" on a server, check the binary's timestamp against the commit you think it contains *before* debugging — a stale binary explains most such mysteries. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would an agent open an issue automatically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could, yes. Github has a high degree of automation support for its features.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(AI has been handling your requests in near-real time, including comments made in my name.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd then appreciate to know what is AI and what is you :-)