diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e7311da..2d76859 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -125,18 +125,23 @@ borrows nothing writes no such line. Some of that a run refuses and some of it it does not, and the difference is worth knowing before you lean on any of it. A `borrowed/` directory with no `LICENSE` beside it is refused. So is a record declaring `Borrowed:` in an -experiment that holds no such directory. So is a directory named `borrowed` +experiment that holds no such directory, and so is the other direction of the +same disagreement, a `borrowed/` directory in an experiment whose record +declares no `Borrowed:` at all. So is a directory named `borrowed` anywhere else inside an experiment, since `experiments//borrowed` is the one place a quarantine lives and one is all record `0019` allows. A directory of that name inside the quarantine is not refused: what is in there is somebody else's code laid out somebody else's way, and this board's rules stop at that edge. -What still passes is a `borrowed/` directory in an experiment whose record -declares nothing, because a field added to the format after +The direction that reads an undeclared quarantine is refused on the directory +and never on the absent field, and that is the reason it is allowed to exist. [docs/decisions/0013-how-the-record-format-changes.md](docs/decisions/0013-how-the-record-format-changes.md) -is never refused for being absent. That one is yours to keep rather than the -gate's. +says a field added to the format after it is optional and that an absent field +is never a refusal, and nothing here reads an absence: the subject is a +directory that is present, and a tree carrying one has already said it borrows +before any header is opened. An experiment that borrows nothing still writes +nothing and is still never asked about the field. Nothing opens the licence file. A green run says the layout and the declaration do not contradict each other, and it says nothing about which licence the code diff --git a/docs/experiment-template.md b/docs/experiment-template.md index 814b5e7..7eebd64 100644 --- a/docs/experiment-template.md +++ b/docs/experiment-template.md @@ -33,7 +33,8 @@ field filled in teaches every new record to declare a value it does not have, an almost every experiment borrows nothing. The code itself goes in `experiments//borrowed/`, which carries its own `LICENSE` naming those terms, and a record declaring the field with no such directory is refused, as is -a borrowed directory with no licence file in it. +a borrowed directory with no licence file in it and a borrowed directory in an +experiment whose record declares the field nowhere. That directory is the only place a quarantine may be, and one is all record `0019` allows, so a directory named `borrowed` anywhere else in the experiment @@ -43,8 +44,10 @@ by whoever wrote it and this board does not rearrange it. What that refusal does not do is worth knowing before you rely on it. Nothing reads the licence file, so a green run says the layout and the declaration agree and says nothing about which licence the code is actually under or whether the -result may be promoted anywhere. A borrowed directory in an experiment whose -record declares nothing passes, because an absent field is never refused. +result may be promoted anywhere. The undeclared quarantine is refused on the +directory rather than on the missing field, so an experiment that borrows +nothing is still never asked for one: an absent field is refused nowhere here, +and what is read is a directory that is there. Add `Held-back` where the experiment is held back under `docs/decisions/0010-a-flaw-in-shipped-software.md`, with the date of the report diff --git a/internal/check/borrowed.go b/internal/check/borrowed.go index fc1af6c..8f6cbdc 100644 --- a/internal/check/borrowed.go +++ b/internal/check/borrowed.go @@ -69,6 +69,31 @@ const ( // quarantine is undeclared by construction however carefully the header // was written. AQuarantineOutsideThePlaceQuarantinesLive = "quarantine-outside-the-place-quarantines-live" + + // BorrowedDirectoryTheRecordDoesNotDeclare refuses an experiment that holds + // a quarantine while its record declares no Borrowed field. That is the + // second direction of the disagreement above: the tree says the experiment + // borrows and the record says nothing, so the person promoting the work + // reads a boundary and finds no source and no licence named anywhere they + // would look for one. + // + // IT IS KEYED ON THE DIRECTORY AND NOT ON THE ABSENT FIELD, and the + // difference is the whole reason it may exist. Record 0013 says a field + // added to the format after it is optional and that an absent field is + // never a refusal, which is why refuseHardware declines the identical shape + // one field over. Nothing here reads an absence and refuses it: what is + // refused is a directory that is present, and a tree carrying one has + // already said it borrows without the header being consulted at all. So + // every experiment that borrows nothing goes on writing nothing, which is + // the property record 0013 bought and this does not spend. + // + // WHERE IT DOES NOT REACH. A quarantine somewhere other than + // experiments//borrowed is not this arm's subject - it is refused by + // the arm above, whose repair is to move it, and this one then reads the + // moved directory. So an experiment whose only borrowed directory is in the + // wrong place is refused once rather than twice, and the second refusal + // arrives with the repair rather than beside the defect. + BorrowedDirectoryTheRecordDoesNotDeclare = "borrowed-directory-the-record-does-not-declare" ) // refuseBorrowed holds an experiment's borrowed quarantine and its record's @@ -82,13 +107,7 @@ const ( // record 0019 explicitly leaves undecided. What passes here is a layout and a // declaration that do not contradict each other, and nothing further. // -// WHERE IT DOES NOT REACH, in three places rather than one. -// -// A borrowed directory in an experiment whose record declares no Borrowed field -// passes. That is the second direction of the disagreement above and it is a -// refusal on an absent field, which record 0013 forbids in the words -// refuseHardware already declines the same shape in. Closing it is a change to -// that record rather than a wider check here. +// WHERE IT DOES NOT REACH, in two places rather than three. // // A Borrowed declaration written with nothing after the colon is a declaration, // so the directory half above is read against it, and nothing here asks whether @@ -141,16 +160,26 @@ func refuseBorrowed(fsys fs.FS, root, inside, record string, data []byte) ([]Ref if err != nil { return refusals, nil } - if _, declared := parsed.Field(FieldBorrowed); !declared || held { - return refusals, nil + _, declared := parsed.Field(FieldBorrowed) + + switch { + case declared && !held: + refusals = append(refusals, Refusal{ + Property: RecordBorrowedDeclarationNamesNoDirectory, + Subject: record, + Detail: fmt.Sprintf("it declares %s and there is no %s directory in %s, so the record says the experiment borrows and the tree says it does not", + FieldBorrowed, BorrowedDir, inside), + }) + case held && !declared: + refusals = append(refusals, Refusal{ + Property: BorrowedDirectoryTheRecordDoesNotDeclare, + Subject: at(root, quarantine), + Detail: fmt.Sprintf("it holds code under somebody else's terms and %s declares no %s, so the tree says the experiment borrows and the record says nothing. record 0019 puts the source and the licence in that field", + record, FieldBorrowed), + }) } - return append(refusals, Refusal{ - Property: RecordBorrowedDeclarationNamesNoDirectory, - Subject: record, - Detail: fmt.Sprintf("it declares %s and there is no %s directory in %s, so the record says the experiment borrows and the tree says it does not", - FieldBorrowed, BorrowedDir, inside), - }), nil + return refusals, nil } // refuseQuarantineElsewhere walks an experiment for a directory named borrowed diff --git a/testdata/cases/a-borrowed-directory-the-record-does-not-declare/expected b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/expected new file mode 100644 index 0000000..466fe70 --- /dev/null +++ b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/expected @@ -0,0 +1,4 @@ +directories 1 +records 1 +experiments present +decisions absent diff --git a/testdata/cases/a-borrowed-directory-the-record-does-not-declare/expected-refusals b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/expected-refusals new file mode 100644 index 0000000..86362fb --- /dev/null +++ b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/expected-refusals @@ -0,0 +1 @@ +borrowed-directory-the-record-does-not-declare diff --git a/testdata/cases/a-borrowed-directory-the-record-does-not-declare/near-neighbour b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/near-neighbour new file mode 100644 index 0000000..bfa66fd --- /dev/null +++ b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/near-neighbour @@ -0,0 +1 @@ +an-experiment-that-borrows-and-declares-it diff --git a/testdata/cases/a-borrowed-directory-the-record-does-not-declare/tree/experiments/one/EXPERIMENT.md b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/tree/experiments/one/EXPERIMENT.md new file mode 100644 index 0000000..e473fd7 --- /dev/null +++ b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/tree/experiments/one/EXPERIMENT.md @@ -0,0 +1,14 @@ +Slug: one +State: asking +Question-Written: 2026-01-01 +Needs-Hardware: none + +## Question + +Does the reference implementation lose a frame when the stream stalls? + +## Method + +The implementation was read and run from the copy this experiment carries. + +## Answer diff --git a/testdata/cases/a-borrowed-directory-the-record-does-not-declare/tree/experiments/one/borrowed/LICENSE b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/tree/experiments/one/borrowed/LICENSE new file mode 100644 index 0000000..43602d7 --- /dev/null +++ b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/tree/experiments/one/borrowed/LICENSE @@ -0,0 +1,7 @@ +MIT License + +Copyright (c) 2026 the author of the borrowed implementation + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files, to deal in the software +without restriction. diff --git a/testdata/cases/a-borrowed-directory-the-record-does-not-declare/tree/experiments/one/borrowed/source.txt b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/tree/experiments/one/borrowed/source.txt new file mode 100644 index 0000000..57238bd --- /dev/null +++ b/testdata/cases/a-borrowed-directory-the-record-does-not-declare/tree/experiments/one/borrowed/source.txt @@ -0,0 +1 @@ +The borrowed implementation would sit here.