From c4c6d03612fcd2c652d8d019ee91d4702dfc15b0 Mon Sep 17 00:00:00 2001 From: Hawkynt Date: Fri, 4 Sep 2026 19:36:00 +0200 Subject: [PATCH] * the house style is written down where the tooling reads it, and where an implementation may come from The .editorconfig carried an override forcing a 4-space indent on C# and project files. That has never been this repository's style. Measured over its own source, ignoring vendored and generated files: opening brace on its own line 2 opening brace on the same line 3494 and the leading-space histogram has 7321 lines at two and 5514 at six, which only occur on a two-space ladder. The override is removed -- [*] already gives 2 -- and a [*.cs] block now states the K&R brace rules in the form Roslyn can actually enforce, which nothing did. AGENTS.md gains the sourcing ladder from the template: licence-compatible source we can take outright, either vendored verbatim or converted into house style; then the clean-room path for source we cannot take, read for a specification, test cases and an oracle; then the normative specification, trusted secondary write-ups, and last untrusted material needing independent agreement. Constants sit outside the ladder because they cut across it -- tables, S-boxes and polynomials are facts, not expression, and get copied exactly. --- .editorconfig | 9 +++++++-- AGENTS.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index b9c85d0..5bb846f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,8 +9,13 @@ trim_trailing_whitespace = true indent_style = space indent_size = 2 -[*.{cs,csproj,props,targets}] -indent_size = 4 +[*.cs] +# K&R: the opening brace ends the line that opens the block, and else/catch/finally +# continue the line that closed the previous one. Indentation is the 2 spaces from [*]. +csharp_new_line_before_open_brace = none +csharp_new_line_before_else = false +csharp_new_line_before_catch = false +csharp_new_line_before_finally = false [*.{md,markdown}] trim_trailing_whitespace = false # trailing spaces are hard line-breaks diff --git a/AGENTS.md b/AGENTS.md index f4449d3..b138850 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -40,6 +40,61 @@ public listing validates). Stable releases are **manual** (`gh workflow run release.yml`) — never cut one unless explicitly asked. +## Sourcing an implementation + +Never write a format, codec, cipher or compression scheme out of your own understanding when +somebody has already got it right. Work **down** this ladder, stop at the first rung that applies, +and say in the commit body which rung you used and why the ones above it did not. + +**1 — Licence-compatible source you can take.** MIT, BSD, Apache-2.0, LGPL, public domain: anything +this repository's LGPL-3.0-or-later can absorb. Search for it before writing anything. There are two +ways to take it and the choice is not cosmetic: + +- **Vendor it** — a verbatim subtree under `Vendored//` next to its own `LICENSE.txt`, kept + in the upstream's own formatting. Do *not* restyle it: the whole point is that the next upstream + version still applies cleanly, and a reformatted copy conflicts on every update. Keep it out of + the published API surface with the `exclude-namespace` input of the `package-readme` action rather + than by editing the source. +- **Convert it** — carry the algorithm across into this codebase properly. Converted code is *our* + code, so every rule under "Code conventions" applies to it, including the current C# language + version (C# 14) wherever that says the same thing more plainly. Do not restate those rules + here or anywhere else: one stale copy of them is how this guide spent years asking for a brace + style the code had never used. A conversion that still reads like C, or like a decompiler's + output, is not finished. + +Either way, record where it came from — a `THIRD_PARTY_NOTICES.md` in the package, or a +`THIRD-PARTY-NOTICE..txt` beside the code. Attribution is a licence term, not a courtesy. + +**2 — Licence-incompatible source: use it, but not its code.** GPL where we ship LGPL, anything +proprietary, anything with no licence at all. Read it and *build material from it*: a written +specification, a set of test cases, and a third-party oracle you can run to produce expected output. +Then implement from that derived material. Do not paste it, do not transliterate it line by line, +and do not carry its file layout or its identifier names across — that is still the same copy. + +**Constants are not expression.** Tables, S-boxes, magic numbers, CRC polynomials, Huffman code +tables, quantisation matrices, window and filter coefficients: copy them exactly, from whichever +source is authoritative, on every rung of this ladder. A re-derived S-box is simply a wrong S-box, +and a table somebody worked out for themselves is the defect that nothing catches until real files +arrive. Where a value is arbitrary-but-agreed, matching it *is* the specification. + +**3 — Original reference material.** The specification, the standard (RFC, ITU-T, ISO, ECMA), the +academic paper, the vendor's own documentation, the format author's write-up. Prefer the normative +text over anybody's description of it; where the two disagree, the normative text wins and the +disagreement is worth a comment. + +**4 — Other trusted sources.** Reverse-engineering write-ups, articles and blog posts by named +people with a track record, and long-lived project wikis that cite their evidence. + +**5 — Untrusted material, by agreement only.** Forum answers, unattributed gists, wiki edits with no +provenance. Only when nothing above exists, and only where several *independent* sources agree — +majority vote, discounting the ones that plainly copied each other. Treat the result as a hypothesis +and mark it as one in the code. + +Whatever rung you land on, the finished implementation is judged the same way: it must agree with an +oracle or with real files, not merely compile and look plausible. When a licence-incompatible +implementation was your oracle, keep the comparison as a test wherever it can run, and where it +cannot, commit the captured expected output with a note saying what produced it. + ## Code conventions - Latest C# features; namespaces/assemblies are `Hawkynt.PhotoManager.*`