From d5d32c37c7523dfed07408a1a5409f4fa18353a2 Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sun, 8 Nov 2026 11:43:19 +0100 Subject: [PATCH 1/9] chore: add the Rusuban rules and locks of this repo The rules Rusuban's agents follow on this repo, read from the default branch: what they do alone and what comes to the maintainer, what merges alone and how this repo merges, review rules, and how they write on GitHub. locks.json holds what the server checks without the model: supply-chain paths, size limits, the zones that need a rendering and performance proof, CodeRabbit required, and the Nix build and notification workflows ignored. --- .rusuban/locks.json | 50 +++++++++++++++++++++++ .rusuban/rules/01-autonomy.md | 68 ++++++++++++++++++++++++++++++++ .rusuban/rules/02-merging.md | 74 +++++++++++++++++++++++++++++++++++ .rusuban/rules/03-review.md | 47 ++++++++++++++++++++++ .rusuban/rules/04-github.md | 16 ++++++++ 5 files changed, 255 insertions(+) create mode 100644 .rusuban/locks.json create mode 100644 .rusuban/rules/01-autonomy.md create mode 100644 .rusuban/rules/02-merging.md create mode 100644 .rusuban/rules/03-review.md create mode 100644 .rusuban/rules/04-github.md diff --git a/.rusuban/locks.json b/.rusuban/locks.json new file mode 100644 index 000000000..4828358bb --- /dev/null +++ b/.rusuban/locks.json @@ -0,0 +1,50 @@ +{ + "mergeMethod": "rebase", + "lockedPaths": [ + ".github/**", + "scripts/**", + "nix/**", + "flake.*", + "package.json", + "package-lock.json", + "Cargo.toml", + "Cargo.lock", + "electron-builder.*", + ".npmrc" + ], + "maxLines": 300, + "maxFiles": 15, + "sizeExempt": [ + "*.test.*", + "**/tests/**", + "**/test/**", + "**/__tests__/**", + "**/fixtures/**", + "*.md", + "technical-documentation/**", + "docs/**" + ], + "requiredChecks": ["CodeRabbit"], + "ignoredChecks": [ + "nix build .#openscreen", + "Sync PR activity to Discord", + "Sync ROADMAP.md to Discord", + "Mark linked issues fixed in main" + ], + "evidence": [ + { + "paths": [ + "crates/compositor/**", + "electron/native/**", + "electron/recording/**", + "src/native/**", + "src/lib/exporter/**", + "*Preview*.js", + "*Preview*.jsx", + "*Preview*.ts", + "*Preview*.tsx" + ], + "what": "a pixel-identical export of the reference project, and export time and preview frame rate within ±5 % of the base" + } + ] +} diff --git a/.rusuban/rules/01-autonomy.md b/.rusuban/rules/01-autonomy.md new file mode 100644 index 000000000..1c78216df --- /dev/null +++ b/.rusuban/rules/01-autonomy.md @@ -0,0 +1,68 @@ +# What the agents do alone, and what comes to the owner + +The owner is @EtienneLescot. Every card goes to him. + +## Alone + +The agents act alone on everything that is not a product or architecture decision: + +- fix a bug, and merge a PR that is not a feature once its gates are green (see 02-merging); +- approve a fork's CI after reading the diff; +- ask for a rebase, a fix or missing information; +- close a duplicate, an item that was replaced, or one that came due. + +## To the owner, always with a card + +- A feature, issue or PR. +- A change of UI or UX: visible English text, style, layout, a default value, a setting. +- An architecture choice: a new module, a new dependency, a new IPC or API surface, a data format. +- An impact on pixels, rendering or performance that no proof has ruled out. +- A refusal: declining a PR, closing a feature request, or answering a product question. + +## Issues + +- **A bug that can be reproduced and is documented enough**: the agents own it, and a worker fixes it. +- **A bug without enough information**: it waits on its reporter (`owner: "third"`, `waits: "@login"`). + Post one factual question. +- **A product, UI or architecture request**: to the owner, with a card. +- **A duplicate**: set `links.duplicateOf`, post a factual comment and close it. + +## Waiting on a third party: two days at most + +An item that waits on someone (a reporter, an author, a contributor, a merge, a release) comes back +two days later (`revisitAt`). Read the thread first: if they answered in the last two days, take the +answer in and judge again. Otherwise, move on without them. + +- **A bug fix or a consolidation** (bug, maintenance, cleanup, robustness, translation): the agents + own it, and a worker moves it forward. + - An issue: fix it from what is known (the thread, logs, the code, a reproduction on a machine the + agents can reach) and open the PR. + - A contributor's PR: finish it in their place, on their fork's branch, without closing their PR + (rebase, fixes, review threads). They keep the credit. + - A wait on a merge or a release: check whether it happened, then close the item or push what + blocks it. + - Close only when the code gives no lead and no machine reproduces it, with a factual comment that + invites a reopen with the missing information. +- **A new feature**, issue or PR: to the owner, with a card that presents it as it is: what is done, + what is missing. Offer actions you will take: merge it as it is, finish it yourself, keep it open as + "help wanted", or close it. + +Never hand a two-day wait back to the third party without a recent answer from them: that would be a +silent wait. + +## Nothing stays with the agents without work + +An item the agents own comes back after one day at most (`revisitAt`). With no work in progress, +delegate it to a worker, hand it to a named third party, or bring it to the owner with a card. + +## Priority + +- **P0**: a crash, lost data, or a recording or an export that fails, in a released version. +- **P1**: a core flow degraded (capture, preview, editing, export), or a regression. +- **P2**: any other bug, and maintenance. +- **P3**: cosmetic, and nice to have. + +## Areas + +`capture`, `preview`, `export`, `editor`, `ai`, `mcp`, `i18n`, `packaging`, `tooling`, `storage`, +`webcam`, `audio`. diff --git a/.rusuban/rules/02-merging.md b/.rusuban/rules/02-merging.md new file mode 100644 index 000000000..f0e1bc746 --- /dev/null +++ b/.rusuban/rules/02-merging.md @@ -0,0 +1,74 @@ +# What merges alone, and how this repo merges + +## A PR may merge alone (`pr.auto: true`) + +It applies to every author, contributors included, judged on the head you read. A PR merges alone +only when it is one of these: + +- a bug fix; +- a translation into a language other than English; +- documentation; +- tests; +- maintenance. + +It never merges alone when it is: + +- a feature; +- a change of UI or UX; +- an architecture choice; +- an impact on pixels, rendering or performance that a proof has not ruled out. + +**A bug** is behavior that contradicts what is expected or documented: a crash, a desync, a wrong +export. A new setting, an interface text, a default value or a new visible behavior is a feature. + +The locks file adds what the server checks alone: + +- the supply-chain paths (CI, scripts, dependencies, packaging) never merge alone; +- at most 300 changed lines and 15 files, tests and documentation excluded. + +## Rendering and performance need a proof + +A change to capture, preview, compositor, export or rendering needs a proof of no impact: + +- a pixel-identical export of the reference project; +- export time and preview frame rate within ±5 % of the base, measured in the real app, heavy case + included. + +The locks file names the zones. Elsewhere, set `pr.evidence.needed: true` yourself when the change can +reach the picture or its timing. A worker other than the judge makes the proof and records it. + +Performance comes first. A correctness fix that costs latency is split in two: + +- the part that costs nothing goes on its own; +- the rest goes to the owner as an explicit trade-off, on a card. + +## Rebase only + +- **This repo merges by rebase only, with no merge commits and no squash.** +- **Conflicts are fixed by rebasing on the base, never by a merge commit.** With a merge commit, GitHub + still calls the PR mergeable, but it cannot rebase it. Check the REST field `rebaseable`, not + `mergeable`. +- **During a train of merges, `rebaseable` can be stale.** Rebase on main, push, and wait for CI. +- **Merge first the PRs that touch shared files**, such as the end-to-end checklist and the locales. + +## No closing keyword in a commit + +- **A rebase merge replays every commit.** A `Fixes #N` in a commit closes the issue, even when the PR + only says "Part of #N". +- **Closing keywords** (`Fixes`, `Closes`, `Resolves`) belong in the PR's description only, and only + when the PR completes the issue. Agents write `Refs #N`. +- **Before a partial fix merges**, read its commit messages. + +## Checks + +- **The Nix build is not a merge gate**: the locks file ignores it. +- **Do not trust the CI rollup on a fork's PR.** Its workflows wait for an approval, while the Discord + sync and CodeRabbit pass without one, so the rollup can read green when no real job ran. Judge from + the CI workflow's own run on the head. + +## Features run on the three systems + +- **A feature must work on macOS, Windows and Linux.** A feature PR limited to one system is not merged. +- **Before you propose to merge a feature, check the three systems.** If one is missing, comment to + ask the contributor for the port and a short end-to-end video per system (a real capture and an + export). diff --git a/.rusuban/rules/03-review.md b/.rusuban/rules/03-review.md new file mode 100644 index 000000000..9aa1bfebc --- /dev/null +++ b/.rusuban/rules/03-review.md @@ -0,0 +1,47 @@ +# Reviewing + +These are what the owner has turned down after CI was green. Check them before you recommend a merge. + +## Interface + +- **Every control has a visible effect in every reasonable state, not only at the edges.** If what it + changes is invisible, show it on the canvas or drop the control. +- **One control, one axis.** Two controls never fight over the same visible result, and a control + never moves an axis it does not name. +- **No raw internal values shown to the user**, such as signed percentages for a position. +- **One style per row**: never text buttons and icon buttons mixed in the same panel. +- **No explanatory sentence under a setting.** The label says it. +- **An option that does nothing in the current context is hidden**, not greyed out with a reason. +- **The one exception is a warning that prevents a real surprise.** +- **An automatic mode is available only on homogeneous inputs.** On mixed inputs it is not offered. +- **Prefer fixing the model underneath** to adding presets or controls over a broken one. + +## Translations + +- **Every new text key exists in the locale files.** A key missing everywhere shows raw in the app. +- **The locale check is not enough.** It only compares the locales with one another, and the tests mock + the translation function. + +## Performance + +**A PR on preview, capture, compositor or export carries before-and-after numbers**, measured in the +real app, heavy case included: + +- frame rate; +- time per frame; +- seek latency; +- CPU and GPU; +- frames dropped. + +No numbers, no merge. + +## PRs that meet + +- **Two PRs green on their own can break main together.** When a PR changes what a shared function does, + for example it no longer throws, look at every caller, including those another open PR adds. +- **When two open PRs touch the same files**, set `links.before` so the order is explicit. + +## Fixes made by workers + +- **A fix is made in the worker's own worktree**, on a new branch, and its PR is opened with `Refs #N`. +- **The repo's AGENTS.md applies before the PR**: targeted tests, both typechecks, and lint. diff --git a/.rusuban/rules/04-github.md b/.rusuban/rules/04-github.md new file mode 100644 index 000000000..a8bb1ac0e --- /dev/null +++ b/.rusuban/rules/04-github.md @@ -0,0 +1,16 @@ +# Writing on GitHub + +- **Every message on GitHub is in English**: short, warm and factual. +- **What agents may post on their own is factual.** + - Allowed: fixed in a version, a request for information, a duplicate, a reminder, a review of a + bug fix, a request to rebase. + - Never on your own, always a card first: a refusal, closing a feature, a product answer. +- **Thank contributors.** When you finish a contributor's PR, it stays theirs: + - push to their fork's branch, as the maintainer can; + - keep their PR open; + - rebase it, never merge main into it; + - their name stays on their commits. +- **Approve a fork's CI only after reading the head's diff.** + - The diff must hold no secret, no network access, no install hook, and no doubtful dependency. + - Read any change under `.github/` or `scripts/` line by line. If in doubt, write a card. + - Approving one contributor's runs also releases their other open PRs: read those diffs too. From 94ef9f97e3712e6b5d582163526c7b8972d67efb Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sun, 8 Nov 2026 12:01:42 +0100 Subject: [PATCH 2/9] chore: spec files exempt from the size limit, the capture bridge proven, contributor PRs kept From the review: *.spec.* files are tests; electron/native-bridge/ is capture code and needs the rendering proof; a fork that refuses maintainer edits gets a fallback that keeps the contributor's commits; a worker finishes a contributor's PR on their branch, never in a competing one. --- .rusuban/locks.json | 2 ++ .rusuban/rules/01-autonomy.md | 3 +++ .rusuban/rules/03-review.md | 5 ++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.rusuban/locks.json b/.rusuban/locks.json index 4828358bb..36d11ac2b 100644 --- a/.rusuban/locks.json +++ b/.rusuban/locks.json @@ -16,6 +16,7 @@ "maxFiles": 15, "sizeExempt": [ "*.test.*", + "*.spec.*", "**/tests/**", "**/test/**", "**/__tests__/**", @@ -36,6 +37,7 @@ "paths": [ "crates/compositor/**", "electron/native/**", + "electron/native-bridge/**", "electron/recording/**", "src/native/**", "src/lib/exporter/**", diff --git a/.rusuban/rules/01-autonomy.md b/.rusuban/rules/01-autonomy.md index 1c78216df..f7b39fd17 100644 --- a/.rusuban/rules/01-autonomy.md +++ b/.rusuban/rules/01-autonomy.md @@ -39,6 +39,9 @@ answer in and judge again. Otherwise, move on without them. agents can reach) and open the PR. - A contributor's PR: finish it in their place, on their fork's branch, without closing their PR (rebase, fixes, review threads). They keep the credit. + - If their fork refuses maintainer edits, ask them to allow them. Without an answer in two days, + carry their commits to a new PR from a worker branch, their name still on their commits. + Link the two PRs, and say so on theirs. - A wait on a merge or a release: check whether it happened, then close the item or push what blocks it. - Close only when the code gives no lead and no machine reproduces it, with a factual comment that diff --git a/.rusuban/rules/03-review.md b/.rusuban/rules/03-review.md index 9aa1bfebc..240192e23 100644 --- a/.rusuban/rules/03-review.md +++ b/.rusuban/rules/03-review.md @@ -43,5 +43,8 @@ No numbers, no merge. ## Fixes made by workers -- **A fix is made in the worker's own worktree**, on a new branch, and its PR is opened with `Refs #N`. +- **A fix of an issue is made in the worker's own worktree**, on a new branch, and its PR is opened + with `Refs #N`. +- **Finishing a contributor's PR happens on their branch**, never in a competing PR (see + 01-autonomy). - **The repo's AGENTS.md applies before the PR**: targeted tests, both typechecks, and lint. From 698a5a727a006de8713ad02fe0eec5699bb9b656 Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sun, 8 Nov 2026 12:28:20 +0100 Subject: [PATCH 3/9] chore: CodeRabbit asked again when skipped, a contributor's commits read before they are carried - Every card goes to the owner. - A review cancelled or skipped by CodeRabbit's hourly limit: `@coderabbitai review` once per head, then wait. - A contributor's commits carried to a new PR are read first: one touching `.github/`, `scripts/` or the build is never pushed here, where its workflows would run with the repo's secrets; the new PR carries the closing reference; the original's head is read again before it merges. --- .rusuban/rules/01-autonomy.md | 11 ++++++++--- .rusuban/rules/02-merging.md | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.rusuban/rules/01-autonomy.md b/.rusuban/rules/01-autonomy.md index f7b39fd17..dbaa16a91 100644 --- a/.rusuban/rules/01-autonomy.md +++ b/.rusuban/rules/01-autonomy.md @@ -1,6 +1,6 @@ # What the agents do alone, and what comes to the owner -The owner is @EtienneLescot. Every card goes to him. +The owner is @EtienneLescot. Every card goes to the owner. ## Alone @@ -40,8 +40,13 @@ answer in and judge again. Otherwise, move on without them. - A contributor's PR: finish it in their place, on their fork's branch, without closing their PR (rebase, fixes, review threads). They keep the credit. - If their fork refuses maintainer edits, ask them to allow them. Without an answer in two days, - carry their commits to a new PR from a worker branch, their name still on their commits. - Link the two PRs, and say so on theirs. + carry their commits to a new PR from a worker branch, their name still on their commits: + - read every commit first. One that touches `.github/`, `scripts/` or the build is never pushed + to this repo, where its workflows would run with the repo's secrets: that PR goes to the owner + on a card; + - link the two PRs, and say so on theirs. When theirs would close an issue, the new PR's + description carries its closing reference; + - before the new PR merges, read their PR's head again and bring in what they pushed since. - A wait on a merge or a release: check whether it happened, then close the item or push what blocks it. - Close only when the code gives no lead and no machine reproduces it, with a factual comment that diff --git a/.rusuban/rules/02-merging.md b/.rusuban/rules/02-merging.md index f0e1bc746..a2e7007f5 100644 --- a/.rusuban/rules/02-merging.md +++ b/.rusuban/rules/02-merging.md @@ -62,6 +62,8 @@ Performance comes first. A correctness fix that costs latency is split in two: ## Checks - **The Nix build is not a merge gate**: the locks file ignores it. +- **CodeRabbit is required.** When its review is cancelled or skipped (it reviews at most 8 PRs an + hour here), comment `@coderabbitai review` on the PR, once per head, then wait for its review. - **Do not trust the CI rollup on a fork's PR.** Its workflows wait for an approval, while the Discord sync and CodeRabbit pass without one, so the rollup can read green when no real job ran. Judge from the CI workflow's own run on the head. From 01275c7d882a8fa5306e641693f3271f5182aad3 Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sun, 8 Nov 2026 13:08:00 +0100 Subject: [PATCH 4/9] chore: a contributor's commits carried from a fork, never a branch here; CodeRabbit asked twice at most --- .rusuban/rules/01-autonomy.md | 11 +++++++---- .rusuban/rules/02-merging.md | 4 +++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.rusuban/rules/01-autonomy.md b/.rusuban/rules/01-autonomy.md index dbaa16a91..a756717eb 100644 --- a/.rusuban/rules/01-autonomy.md +++ b/.rusuban/rules/01-autonomy.md @@ -40,13 +40,16 @@ answer in and judge again. Otherwise, move on without them. - A contributor's PR: finish it in their place, on their fork's branch, without closing their PR (rebase, fixes, review threads). They keep the credit. - If their fork refuses maintainer edits, ask them to allow them. Without an answer in two days, - carry their commits to a new PR from a worker branch, their name still on their commits: - - read every commit first. One that touches `.github/`, `scripts/` or the build is never pushed - to this repo, where its workflows would run with the repo's secrets: that PR goes to the owner - on a card; + carry their commits to a new PR from a fork under your account, never from a branch of this + repo: there, their tests and their build would run with the repo's secrets and a token that + can write. Their name stays on their commits: + - read every commit first. One that touches `.github/`, `scripts/` or the build goes to the + owner on a card; - link the two PRs, and say so on theirs. When theirs would close an issue, the new PR's description carries its closing reference; - before the new PR merges, read their PR's head again and bring in what they pushed since. + What they push after it merged goes into a follow-up PR, and the issue it closed is reopened + if it is not complete without that. - A wait on a merge or a release: check whether it happened, then close the item or push what blocks it. - Close only when the code gives no lead and no machine reproduces it, with a factual comment that diff --git a/.rusuban/rules/02-merging.md b/.rusuban/rules/02-merging.md index a2e7007f5..6baa0058f 100644 --- a/.rusuban/rules/02-merging.md +++ b/.rusuban/rules/02-merging.md @@ -63,7 +63,9 @@ Performance comes first. A correctness fix that costs latency is split in two: - **The Nix build is not a merge gate**: the locks file ignores it. - **CodeRabbit is required.** When its review is cancelled or skipped (it reviews at most 8 PRs an - hour here), comment `@coderabbitai review` on the PR, once per head, then wait for its review. + hour here), comment `@coderabbitai review` on the PR, then wait for its review. If that request is + skipped too, ask once more an hour later; if the second one is skipped as well, the PR goes to the + owner on a card. Never more than two requests per head. - **Do not trust the CI rollup on a fork's PR.** Its workflows wait for an approval, while the Discord sync and CodeRabbit pass without one, so the rollup can read green when no real job ran. Judge from the CI workflow's own run on the head. From a715869f09850f0e0cbcbb07d5c9252f4137b0a5 Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sun, 8 Nov 2026 13:23:13 +0100 Subject: [PATCH 5/9] chore: why a contributor's commits are carried from a fork, and what they push before the merge --- .rusuban/rules/01-autonomy.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.rusuban/rules/01-autonomy.md b/.rusuban/rules/01-autonomy.md index a756717eb..68d4075ce 100644 --- a/.rusuban/rules/01-autonomy.md +++ b/.rusuban/rules/01-autonomy.md @@ -41,15 +41,15 @@ answer in and judge again. Otherwise, move on without them. (rebase, fixes, review threads). They keep the credit. - If their fork refuses maintainer edits, ask them to allow them. Without an answer in two days, carry their commits to a new PR from a fork under your account, never from a branch of this - repo: there, their tests and their build would run with the repo's secrets and a token that - can write. Their name stays on their commits: + repo: a branch here runs its workflows in the repo's trusted context, where secrets can reach + them; a fork's PR never gets secrets or a write token. Their name stays on their commits: - read every commit first. One that touches `.github/`, `scripts/` or the build goes to the owner on a card; - link the two PRs, and say so on theirs. When theirs would close an issue, the new PR's description carries its closing reference; - before the new PR merges, read their PR's head again and bring in what they pushed since. - What they push after it merged goes into a follow-up PR, and the issue it closed is reopened - if it is not complete without that. + Once it merged, compare their head with the last one you carried: anything newer goes into + a follow-up PR, and the issue it closed is reopened if it is not complete without that. - A wait on a merge or a release: check whether it happened, then close the item or push what blocks it. - Close only when the code gives no lead and no machine reproduces it, with a factual comment that From 1d0c7b5e409660fc7186bbf7a789c885f04d731a Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sun, 8 Nov 2026 13:35:09 +0100 Subject: [PATCH 6/9] chore: the agent's fork keeps its Actions off, and a follow-up PR carries the closing reference --- .rusuban/rules/01-autonomy.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.rusuban/rules/01-autonomy.md b/.rusuban/rules/01-autonomy.md index 68d4075ce..d09d284e5 100644 --- a/.rusuban/rules/01-autonomy.md +++ b/.rusuban/rules/01-autonomy.md @@ -40,16 +40,18 @@ answer in and judge again. Otherwise, move on without them. - A contributor's PR: finish it in their place, on their fork's branch, without closing their PR (rebase, fixes, review threads). They keep the credit. - If their fork refuses maintainer edits, ask them to allow them. Without an answer in two days, - carry their commits to a new PR from a fork under your account, never from a branch of this - repo: a branch here runs its workflows in the repo's trusted context, where secrets can reach - them; a fork's PR never gets secrets or a write token. Their name stays on their commits: + carry their commits to a new PR from a fork under your account whose Actions stay disabled, + never from a branch of this repo: a branch here runs its workflows in the repo's trusted + context, where secrets can reach them; a fork's PR never runs its code with secrets or a + write token. Their name stays on their commits: - read every commit first. One that touches `.github/`, `scripts/` or the build goes to the owner on a card; - link the two PRs, and say so on theirs. When theirs would close an issue, the new PR's description carries its closing reference; - before the new PR merges, read their PR's head again and bring in what they pushed since. Once it merged, compare their head with the last one you carried: anything newer goes into - a follow-up PR, and the issue it closed is reopened if it is not complete without that. + a follow-up PR. If the issue the new PR closed is not complete without it, reopen it; the + follow-up's description then carries its closing reference. - A wait on a merge or a release: check whether it happened, then close the item or push what blocks it. - Close only when the code gives no lead and no machine reproduces it, with a factual comment that From 7da453833c7597509a9fa22507246396864f8e83 Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sun, 8 Nov 2026 14:55:17 +0100 Subject: [PATCH 7/9] chore: preview and export share one source of rendering, and the proof compares them --- .rusuban/locks.json | 2 +- .rusuban/rules/02-merging.md | 6 +++++- .rusuban/rules/03-review.md | 6 ++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.rusuban/locks.json b/.rusuban/locks.json index 36d11ac2b..d351a260c 100644 --- a/.rusuban/locks.json +++ b/.rusuban/locks.json @@ -46,7 +46,7 @@ "*Preview*.ts", "*Preview*.tsx" ], - "what": "a pixel-identical export of the reference project, and export time and preview frame rate within ±5 % of the base" + "what": "a pixel-identical export of the reference project; export time and preview frame rate within ±5 % of the base; a preview and an export of the same instant that show the same effects, composition and timing at the preview's size" } ] } diff --git a/.rusuban/rules/02-merging.md b/.rusuban/rules/02-merging.md index 6baa0058f..499da8dc4 100644 --- a/.rusuban/rules/02-merging.md +++ b/.rusuban/rules/02-merging.md @@ -28,11 +28,15 @@ The locks file adds what the server checks alone: ## Rendering and performance need a proof +Preview and export share one source of truth for rendering: what you see is what you export. + A change to capture, preview, compositor, export or rendering needs a proof of no impact: - a pixel-identical export of the reference project; - export time and preview frame rate within ±5 % of the base, measured in the real app, heavy case - included. + included; +- a preview and an export of the same instant, compared at the preview's size: they show the same + effects, with the same composition and the same timing. They need not match pixel for pixel. The locks file names the zones. Elsewhere, set `pr.evidence.needed: true` yourself when the change can reach the picture or its timing. A worker other than the judge makes the proof and records it. diff --git a/.rusuban/rules/03-review.md b/.rusuban/rules/03-review.md index 240192e23..3851adbd3 100644 --- a/.rusuban/rules/03-review.md +++ b/.rusuban/rules/03-review.md @@ -22,6 +22,12 @@ These are what the owner has turned down after CI was green. Check them before y - **The locale check is not enough.** It only compares the locales with one another, and the tests mock the translation function. +## Rendering + +- **Every effect goes through the one source of rendering that preview and export share**: what you + see is what you export. A PR that renders an effect in only one of the two paths, or differently + in each, is not merged. + ## Performance **A PR on preview, capture, compositor or export carries before-and-after numbers**, measured in the From fd9dbd50c3a5ef2642b351258eb94ae3d729f84f Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sun, 8 Nov 2026 16:55:07 +0100 Subject: [PATCH 8/9] chore: a follow-up PR closes the reopened issue only when it completes it --- .rusuban/rules/01-autonomy.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.rusuban/rules/01-autonomy.md b/.rusuban/rules/01-autonomy.md index d09d284e5..d286e9bcc 100644 --- a/.rusuban/rules/01-autonomy.md +++ b/.rusuban/rules/01-autonomy.md @@ -50,8 +50,9 @@ answer in and judge again. Otherwise, move on without them. description carries its closing reference; - before the new PR merges, read their PR's head again and bring in what they pushed since. Once it merged, compare their head with the last one you carried: anything newer goes into - a follow-up PR. If the issue the new PR closed is not complete without it, reopen it; the - follow-up's description then carries its closing reference. + a follow-up PR. If the issue the new PR closed is not complete without it, reopen it. The + follow-up's description carries its closing reference only when it completes the issue, and + `Refs #N` otherwise. - A wait on a merge or a release: check whether it happened, then close the item or push what blocks it. - Close only when the code gives no lead and no machine reproduces it, with a factual comment that From 5503e36c88ce16f2e8be9b3dfee4d0335be46edf Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sun, 8 Nov 2026 17:01:50 +0100 Subject: [PATCH 9/9] chore: a reference to an issue of another repo keeps its repo --- .rusuban/rules/01-autonomy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rusuban/rules/01-autonomy.md b/.rusuban/rules/01-autonomy.md index d286e9bcc..ece892392 100644 --- a/.rusuban/rules/01-autonomy.md +++ b/.rusuban/rules/01-autonomy.md @@ -52,7 +52,7 @@ answer in and judge again. Otherwise, move on without them. Once it merged, compare their head with the last one you carried: anything newer goes into a follow-up PR. If the issue the new PR closed is not complete without it, reopen it. The follow-up's description carries its closing reference only when it completes the issue, and - `Refs #N` otherwise. + `Refs #N` otherwise, `Refs owner/repo#N` for an issue in another repo. - A wait on a merge or a release: check whether it happened, then close the item or push what blocks it. - Close only when the code gives no lead and no machine reproduces it, with a factual comment that