Governance
Contribution · Decision rights
Who decides what, and how. Fork-and-PR model with labelled rejection reasons.
Governance
Who decides what, and how. Short on purpose.
Decision rights
Daniel Ekström (@Nitton76) is the sole maintainer and the only person who merges. Not “usually”. There is no second merger, no rotation, no earned commit bit, and no path by which a contributor accumulates enough standing to bypass review. That is not a statement about trust in contributors — it is a property of what this repository contains. Settings here become real orders against a real account.
| Decision | Who |
|---|---|
What merges to main |
Owner, always |
| What ships to a live chart | Owner, always |
| Whether a config is measured | Automated — scripts/drl_verify.py, run by CI |
| Whether a measured config is adopted | Owner |
| Screen thresholds (T1–T5), adoption floor | Owner, by PR to the constants, with rationale |
Engine behaviour (drl_engine.py) |
Owner, higher bar — see below |
Why nobody gets write access
Contributors work from forks and open pull requests. Nobody is added as a collaborator
with push rights. This is enforced by branch protection on main, not by convention:
- Direct pushes to
main: blocked - Force pushes and branch deletion: blocked
- Every change arrives as a PR
- Review from
CODEOWNERS(the owner) is required to merge - The
Verify ticker configcheck must pass
The owner can still push directly — branch protection is deliberately not set to
“include administrators”, because a solo maintainer locking themselves out of their own
main at 2am is a bigger practical risk than the one that setting protects against.
Two contribution lanes, deliberately unequal
Lane 1 — ticker configs (confirmed-settings/json/*.json). Open. This is where
help is genuinely wanted. A config is data, its blast radius is one instrument, and CI
adjudicates it mechanically. Most PRs should be this.
Lane 2 — engine and screen code (scripts/, pine/). Deliberately hard. A change
here silently alters every number the project has ever published, including the ones
already in LEDGER.md. Open an issue and get agreement on the approach before
writing code. A correctness fix with a failing-case demonstration is welcome; a
refactor, a style pass, or a “while the contributor was in there” cleanup will be closed regardless
of quality.
What gets rejected, stated up front
- Anything that improves in-sample and regresses out-of-sample. This is the single most common failure and it is not close. Per-symbol tuning across 216 symbols won 88% of the time in-sample and 54% out-of-sample; 54% is a coin flip. If your result looks strong in-sample, that is the expected appearance of an overfit.
- Results from a different engine, a different cost assumption, or a different window than this repo uses. Not because they are wrong — because they are not comparable, and an incomparable number in a public ledger is worse than no number.
- A screenshot of a Strategy Tester panel as the sole evidence. Attach it if you like; it is not the argument.
- Curve-fit parameter sets with no stated mechanism. “It backtests well” describes every overfit ever produced.
- Any change to make a specific instrument pass a screen. Thresholds are chosen without reference to who they kill; that is the whole point of them.
Feedback
Every PR gets a decision and a reason. Rejections are labelled so the reason is legible from the issue list rather than buried in a thread:
| Label | Meaning |
|---|---|
accepted |
Merged |
rejected: oos-decay |
Gained in-sample, lost out-of-sample |
rejected: thin-sample |
Under 20 trades; the comparison is noise |
rejected: not-comparable |
Different engine, cost model, or window |
rejected: no-mechanism |
Fits the data with no explanation of why it should |
needs-rework |
Real idea, wrong evidence — resubmit |
out-of-scope |
Refactors, style, speculative features |
needs-rework is not a soft no. It means the idea is worth the second attempt.
Changing this document
By PR, like anything else. The decision-rights table is the part least likely to move.