From 2ee6752d4da1f022ee2996d792a951048c78d9c5 Mon Sep 17 00:00:00 2001
From: Maximilian Kindshofer
Date: Sat, 5 Sep 2026 07:57:30 +0200
Subject: [PATCH 1/3] docs: say in the README that this is a fork, and what
that changes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The README was upstream's product pitch, and it still is below the new
section — deliberately, so an upstream sync stays a sync rather than a merge
argument. What it never said is that this repository is a fork Exkulpa runs
as a network service, which is the fact AGPL-3.0 §13 attaches obligations to,
and that four fork-local rules apply that upstream has no reason to carry.
The badges are rebuilt around what is true here. The CI badge now points at
this fork's workflow instead of upstream's, so it reports our runs and not
somebody else's. The clone commands point at this fork for the same reason.
The two gate badges deliberately state a rule rather than a number. There is
no repository-wide coverage or mutation percentage to report: both gates
grade what a change touches, and a repo total is a figure nobody has to
defend which improves when you measure less. A percentage badge would have
had to be invented or fetched from a third party, and the diff-scoped
mutation score in particular covers five declared files — printing it as a
repository score would be a straightforward misrepresentation. Since both
gates are jobs inside the CI workflow, the CI badge already goes red when
either fails, which is the honest live signal.
The stars badge is gone. On a fork nobody stars it measured nothing.
Co-Authored-By: Claude Opus 5 (1M context)
---
README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 48 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index dc7a0272be..1f75812ad1 100644
--- a/README.md
+++ b/README.md
@@ -22,12 +22,54 @@
-
-
-
-
+
+
+
+
+
+> **The two blue badges state a rule, not a measurement.** There is no
+> repository-wide coverage or mutation percentage here, deliberately: the gates
+> grade **what a change touches**, not the total, because a total is a number
+> nobody has to defend and it improves when you measure less. `diff-coverage`
+> and `mutation` are jobs inside the CI workflow, so the CI badge above goes red
+> when either of them fails. What the two rules actually require is in
+> [CLAUDE.md](CLAUDE.md).
+
+## This is a fork
+
+Upstream is [QuackbackIO/quackback](https://github.com/QuackbackIO/quackback);
+everything below this section is upstream's own description of the product and
+is left as it stands, so a sync stays a sync. This section is the fork-local
+part.
+
+Exkulpa runs this codebase as a network service for its own products. Under
+AGPL-3.0 §13 that carries obligations towards the people using that instance —
+what they are, what is already satisfied, and what is still open is recorded in
+[LEGAL.md](LEGAL.md). Read it before building anything proprietary in here.
+
+Four things differ from upstream and will bite whoever ignores them:
+
+- **Everything written into the repo is English** — code, comments, commits,
+ docs. The conversation around it is German; the file is not. A patch has to be
+ able to go upstream without a translation pass.
+- **The contract comes before the tests, and the tests before the code.** For
+ anything with branches, money, dates, permissions or parsing, the guarantees
+ are written as a numbered list in plain domain language and confirmed _before_
+ a property is written. A property read off the implementation cannot fail.
+- **Two CI gates grade the diff, not the repo** — see the badges above.
+- **Never deploy a moving tag.** A push to `main` publishes
+ `ghcr.io/therealbithive/quackback:main`, which is fine to try things with and
+ wrong to run: a pod rescheduled overnight silently picks up a different build,
+ and afterwards nobody can say which source was running. Every merge gets a
+ `vX.Y.Z-exkulpa.N` tag instead.
+
+The working rules are in [CLAUDE.md](CLAUDE.md), and the concrete gotchas that
+have already cost someone an afternoon are collected in
+[SELF-IMPROVE.md](SELF-IMPROVE.md). Both are fork-local and absent upstream, so
+neither ever conflicts on a sync.
+
@@ -73,7 +115,7 @@ Slack, Linear, Jira, GitHub, GitLab, Asana, ClickUp, Monday, Trello, Notion, Sho
### Docker
```bash
-git clone https://github.com/QuackbackIO/quackback.git
+git clone https://github.com/theRealBithive/quackback.git
cd quackback
cp .env.example .env # Edit with your configuration
docker build -t quackback -f apps/web/Dockerfile .
@@ -97,7 +139,7 @@ See the [Contributing Guide](CONTRIBUTING.md) to get started.
Prerequisites: [Bun](https://bun.sh/) v1.4.0+ and [Docker](https://docker.com/)
```bash
-git clone https://github.com/QuackbackIO/quackback.git
+git clone https://github.com/theRealBithive/quackback.git
cd quackback
bun run setup # Install deps, start Docker, run migrations
bun run db:seed # Optional: seed demo data
From af52f51fee9e1a642a5956cfd69bde23205e5d14 Mon Sep 17 00:00:00 2001
From: Maximilian Kindshofer
Date: Sat, 5 Sep 2026 07:58:08 +0200
Subject: [PATCH 2/3] docs: record what declaring a file in the mutation
manifest actually costs
Adding a manifest entry asserts that the named suites pin the file. On a
pre-existing file that claim is usually false, and the only way to find out
is to run the gate. One file this round cost a dozen small tests to make the
claim true; the next would have cost sixty mutants of untouched error
handling and was backed out instead.
Also records two traps that each cost a run: NoCoverage mutants mean the
entry names too few suites rather than that the code is untested, and editing
the manifest as text puts the new record in `equivalents` too, which the gate
reports as a missing reason.
Co-Authored-By: Claude Opus 5 (1M context)
---
SELF-IMPROVE.md | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/SELF-IMPROVE.md b/SELF-IMPROVE.md
index 5201b665bf..15ee49cb14 100644
--- a/SELF-IMPROVE.md
+++ b/SELF-IMPROVE.md
@@ -310,6 +310,40 @@ database up in one command.
# Resolved
+## 1x — Declaring a file in the mutation manifest is a claim, and it can cost an afternoon to find out it is false
+
+Adding an entry to `scripts/mutation-manifest.json` asserts that the named
+suites, on their own, pin that file's behaviour. The word "asserts" is doing
+real work: on a file that was already in the repository, the claim is usually
+**not** true, and there is no cheap way to find out except running the gate.
+
+Measured while touching two GitLab files with one field each.
+`gitlab/server/inbound.ts` came back with 21 survivors — all but one in guards
+nobody had ever pinned (an issue hook naming no issue, a note whose text is not
+text, an absent author, both 401 bodies). Closing them was worth doing and took
+about a dozen small tests, because the file is pure parsing. Then
+`gitlab/server/hook.ts` came back with **60**: 15 survivors and 45 never
+executed, across outbound error handling the change had not touched. That one
+was backed out — the entry would have been a false claim, and the gate's
+designed answer for an unpinned file is to name it as ungraded.
+
+So: the size of the claim has nothing to do with the size of the diff. Before
+declaring a pre-existing file, run the gate with the entry added and read the
+number before committing to it. A pure module is usually a dozen tests away
+from honest; a module that does I/O in its branches is a work item of its own.
+
+Two smaller traps found on the way:
+
+- `NoCoverage` mutants mean the entry names too few suites, not that the code is
+ untested. `inbound.ts` had 18 of them purely because `verifySignature` lives
+ in that file and is tested from `signature-matrix.test.ts` two directories
+ away. The fix is a second entry in `suites`, not more tests.
+- Editing the manifest with a blind string replace puts the new record in
+ `equivalents` as well as `graded`, because the same `"file":` line matches in
+ both arrays. The gate refuses to run at all and says an equivalence record
+ needs a `why` — which reads like a missing reason rather than a record that
+ should not exist. Edit that file as JSON, not as text.
+
## 1x — A Stryker run leaves two things behind that nothing else guards
Both surfaced within an hour of the mutation gate going green, and neither is
From 236e5d71d3217950328f6c1cbf138221b91fdade Mon Sep 17 00:00:00 2001
From: Maximilian Kindshofer
Date: Sat, 5 Sep 2026 08:02:57 +0200
Subject: [PATCH 3/3] docs(readme): say where the two gates actually bite
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The badge blockquote claimed the CI badge goes red when `diff-coverage`
or `mutation` fails. True as far as it goes — neither job is
`continue-on-error` and neither is skipped on a push — but it reads as if
the green badge on `main` were evidence those two gates found something.
It is not: both compare against the merge base, and on `main` that is
`main`, so the diff is empty and they grade nothing. The evidence is on
the pull request, which is what the badge label says and what the
sentence now says too.
Co-Authored-By: Claude Opus 5 (1M context)
---
README.md | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 1f75812ad1..0c73c35e6e 100644
--- a/README.md
+++ b/README.md
@@ -33,9 +33,10 @@
> repository-wide coverage or mutation percentage here, deliberately: the gates
> grade **what a change touches**, not the total, because a total is a number
> nobody has to defend and it improves when you measure less. `diff-coverage`
-> and `mutation` are jobs inside the CI workflow, so the CI badge above goes red
-> when either of them fails. What the two rules actually require is in
-> [CLAUDE.md](CLAUDE.md).
+> and `mutation` are jobs in the workflow the CI badge reports, and per PR is
+> where they bite: on `main` the comparison base is `main`, so the diff is empty
+> and there is nothing for them to grade. What the two rules actually require is
+> in [CLAUDE.md](CLAUDE.md).
## This is a fork