Set the rule for an experiment that touches real personal data - #202
Merged
Merged
Conversation
The board's privacy document said what happens to real data if an experiment uses it and declined to say whether an experiment may use it at all, naming that as a question somebody else had to answer. The answer was given on #46 on 2026-08-24 and lived only in a tracker comment, which record 0000 refuses to treat as recorded. This writes it down and gives it the one field a machine can read. Record 0025 carries the decision and supersedes 0008 for the field it adds. Real personal data may be read where it belongs to the person running the experiment and where the measurements were agreed in the record before the work started. The host rule stands on top of both, unchanged: the data never enters the tree and only the measurement is written down. `Real-Data` in the record header names what category of data, on whose host and what will be written down about it, or the single word `none`. It is optional, which record 0013 fixes for every field added after it, so no record already on the default branch is turned red by this. What it prevents is an answer nobody can question afterwards. A record saying a library of a hundred thousand items took four minutes to scan reads identically whether the library was the author's own or an employer's, and whether the timing was the agreed measurement or the one that came out best. The declaration puts the difference in front of a reviewer while the answer is still unknown, which is the only moment asking is cheap. `record-real-data-declaration-is-empty` refuses a record that declares the field and writes nothing after the colon. That is the shape the field invites: typed while the question is written, left to be filled in when the work starts, and never reopened. I proved it bites by replacing the refusing arm with a silent pass: `go test -count=1 ./cmd/... ./internal/...` then reddens `internal/check` alone, at the case fixture and at the two message subtests, and every other package stays green. What nothing refuses is written at the check, in record 0025 and in docs/privacy.md rather than left to be inferred from a green run. An experiment that touches real data and declares nothing at all is not refused and cannot be, whose data it was and whether the measurement was agreed in advance are claims no reading of a checkout tests, and the rule that real data never enters the tree still has no mechanism. The means is Go and Markdown, unchanged from the rest of this tree: the refusal is one more arm on the record walk the runner already performs, and the rule is prose because the part a machine can read is one field. Closes #35 Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #35
What this changes
docs/privacy.mdsaid what happens to real data if an experiment uses it anddeclined to say whether an experiment may use it at all, naming that as a wider
question somebody else had to answer. The answer was given on #46 on
2026-08-24 and lived only in a tracker comment, which record 0000 refuses to
treat as recorded:
docs/decisions/0025-real-data-in-an-experiment.mdwrites it down. Realpersonal data may be read where it belongs to the person running the experiment
and where the measurements were agreed in the record before the work started.
The host rule stands on top of both, unchanged and not restated: the data never
enters the tree, in any form, and what may be written down is the measurement.
The record supersedes 0008 for the field it adds, and 0008 gains the one line
record 0000 allows a superseded record to take.
Real-Datain the recordheader names what category of data, on whose host, and what will be written
down about it, or the single word
none:It is optional, which record 0013 fixes for every field added after it, so no
record already on the default branch is turned red by this and none is edited.
internal/check/realdata.gorefuses a record that declares the field andwrites nothing after the colon, under
record-real-data-declaration-is-empty.Three fixtures under
testdata/cases/carry the refusing case, its nearneighbour and the
nonesentinel.docs/experiment-template.mdcarries the field for records written from hereon, and
CONTRIBUTING.mdno longer says this document is unfinished, becausethat is the sentence which stops being true with this change.
This change removes no path.
What failure it prevents
An answer nobody can question afterwards. A record saying a library of a
hundred thousand items took four minutes to scan reads identically whether the
library was the author's own or an employer's, and whether the timing was the
agreed measurement or the one that came out best. Nothing in a finished answer
separates the two, and asking afterwards asks somebody to remember what they
did rather than to confirm what they wrote. The declaration puts the difference
in front of a reviewer in the commit that writes the question, while the answer
is still unknown.
The refusal prevents the narrower failure the field's own shape invites. The
line is typed while the question is being written, the value is left for the
moment the work starts, and the moment the work starts is when nobody reopens
the header. What is left then carries the appearance of a declaration and none
of the content of one, and it reads to anybody scanning the header as a record
that declared its data and was cleared.
What was run
At
7cc5840d0419ba54628488d0205eb0fa7c9c8937, the four commandsCONTRIBUTING.mdnames, in that order.go build,go vetandgofmt -l cmd internaleach printed nothing, which is the passing result forall three.
What that run did not cover, printed by the package that passed:
The runner over this tree:
The guard proved by deleting it. With the refusing arm of
refuseRealDatareplaced by a silent pass, at the same commit:
One package reddens, at the case fixture and at the two message subtests, and
every other package stays green. The arm was restored before the commit above
was made, and the working tree was compared against it rather than trusted.
What this does not do
The refusal reads one shape and the rule is much larger than it. This is the
fourth leg of the done-when met on a stated reading rather than on an unstated
one: a declaration that is present and empty says nothing about what will be
written down, and nothing about the other two parts either, so the property is
named for the shape a checkout can see rather than for the sentence in record
0025 it serves. A reviewer who reads that leg as asking for a refusal which
judges the words after the colon should send this back, because no reading of a
checkout makes that judgement.
An experiment that touches real personal data and declares nothing at all is
refused by nothing, and cannot be: record 0013 makes an absent field legal for
every field added after it, and the runner cannot tell a record that omitted the
field from one written before the field existed. That is the same hole record
0015 accepted for
Needs-Hardwareand it is accepted here for the same price.Whose data it was, whether the measurement was the agreed one, and whether the
declaration was written before the work started are outside every reading of a
checkout. The last of those is a fact about commits, and the runner reads a
checkout rather than a history.
The rule that real data never enters the tree still has no mechanism and can
have none.
docs/privacy.mdsaid so before this change and says so after it,and nothing here narrows that sentence: a record declaring a category and
carrying a sample of it passes every rule in this package.
This change was read by nobody but me. This board has no second reader tonight,
so the deletion proof above stands in place of one rather than beside it.
The diff is 473 lines added and 18 removed, over the inherited 400-line cap. It
is one topic and it is not re-plannable into pieces that mean anything alone:
the rule, the field it is declared in, the refusal over that field and the two
documents that told a reader the question was open all have to arrive together
or the tree contradicts itself between them. Most of the addition is the
decision record and the prose that record obliges.