Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions docs/experiment-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,25 @@ under `internal/hardware`, in a file whose name ends
`_integration_hardware_test.go`, and a record that says one thing while the
directory says the other is refused.

Add `Borrowed` where the experiment starts from code somebody else wrote, naming
where that code came from and the licence it arrives under. It is not in the
header above for the reason `Measurement-Commit` is not: a template that ships a
field filled in teaches every new record to declare a value it does not have, and
almost every experiment borrows nothing. The code itself goes in
`experiments/<slug>/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.

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.

The format is `docs/decisions/0008-the-experiment-record.md`, as added to by
`docs/decisions/0015-an-experiment-declares-the-harness-it-needs.md` and by
`docs/decisions/0016-an-answer-names-the-commit-it-measured.md`. This file is a
`docs/decisions/0015-an-experiment-declares-the-harness-it-needs.md`, by
`docs/decisions/0016-an-answer-names-the-commit-it-measured.md` and by
`docs/decisions/0019-code-under-another-licence.md`. This file is a
convenience and those records are the authority.

## Question
Expand Down
163 changes: 163 additions & 0 deletions internal/check/borrowed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package check

import (
"errors"
"fmt"
"io/fs"
"path"
)

// FieldBorrowed names where borrowed code came from and the licence it arrives
// under. Record 0019 adds it and record 0013 makes it optional, as it makes
// every field added after it, so an experiment that borrows nothing writes
// nothing and that is never a refusal.
//
// It is declared here rather than beside the four record 0008 fixes, which is
// the shape FieldMeasurementCommit already argues for at its own declaration: a
// field a later record adds arrives with the check that reads it, so a checker
// built before the field is unaware of it and a field with no check has nowhere
// to hide.
const FieldBorrowed = "Borrowed"

// BorrowedDir is the one directory inside an experiment that may hold code
// under a licence that is not this board's, and BorrowedLicenceName is the file
// that says which licence that is. Record 0019 fixes both names and puts the
// directory inside the experiment rather than at the root, because record 0002
// refuses a root directory it does not name.
const (
BorrowedDir = "borrowed"
BorrowedLicenceName = "LICENSE"
)

// The properties a borrowed quarantine can be refused for.
const (
// BorrowedDirectoryCarriesNoLicence refuses a borrowed directory with no
// licence file in it. That is the quarantine without the thing that makes
// it one: a directory a reader walking the tree takes for code under
// somebody else's terms, declaring none of them, so the person promoting
// the work later reads the boundary and learns nothing from it.
//
// It is refused whatever the record says, because the layout is what
// record 0019 buys and a header field is visible only to somebody who
// opened the header.
BorrowedDirectoryCarriesNoLicence = "borrowed-directory-carries-no-licence"

// RecordBorrowedDeclarationNamesNoDirectory refuses a record that declares
// Borrowed while the experiment holds no borrowed directory. The record
// then says code under other terms is in the experiment and the tree says
// it is not, and which of the two is wrong decides the repair, so the
// message names both sides rather than restating the rule.
//
// The declaration having been made is what this reads, so record 0013 is
// untouched by it: an absent field says nothing and is not refused here.
RecordBorrowedDeclarationNamesNoDirectory = "record-borrowed-declaration-names-no-directory"
)

// refuseBorrowed holds an experiment's borrowed quarantine and its record's
// Borrowed declaration to each other and to record 0019's layout.
//
// WHAT A GREEN RUN DOES NOT SAY, and it is most of what somebody wants when
// they read the word licence. Whether the licence file names the licence the
// code is actually under is a judgement about the world rather than about the
// tree, and nothing here opens that file or reads a word of it. So is whether
// the borrowed code may be promoted into a board under other terms, which
// 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.
//
// 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
// it names a source or a licence. Record 0019 says the field names both;
// whether it does is prose a reader judges.
//
// An experiment whose record the walk did not reach - absent, unreadable, above
// the size bound - is not judged here at all, because this is called with the
// record's bytes in hand and those runs never get that far.
//
// A record whose bytes do not parse as a record is judged for its directory and
// not for its declaration, for the reason refuseState and refuseHardware both
// give: nothing can read a field out of a file that has no header.
func refuseBorrowed(fsys fs.FS, root, inside, record string, data []byte) ([]Refusal, error) {
quarantine := path.Join(inside, BorrowedDir)

held, err := isDirectory(fsys, quarantine)
if err != nil {
return nil, fmt.Errorf("cannot read %s: %w", at(root, quarantine), err)
}

var refusals []Refusal

if held {
carried, err := isRegularFile(fsys, path.Join(quarantine, BorrowedLicenceName))
if err != nil {
return nil, fmt.Errorf("cannot read %s: %w", at(root, path.Join(quarantine, BorrowedLicenceName)), err)
}
if !carried {
refusals = append(refusals, Refusal{
Property: BorrowedDirectoryCarriesNoLicence,
Subject: at(root, quarantine),
Detail: fmt.Sprintf("it holds no %s, so it reads as code under somebody else's terms and names none of them. record 0019 puts that file at %s",
BorrowedLicenceName, path.Join(quarantine, BorrowedLicenceName)),
})
}
}

parsed, err := ParseRecord(data)
if err != nil {
return refusals, nil
}
if _, declared := parsed.Field(FieldBorrowed); !declared || held {
return refusals, nil
}

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
}

// isDirectory says whether a name in the walked filesystem is a directory. A
// name that is not there is not one, and that is the ordinary answer rather
// than an error: almost every experiment borrows nothing.
//
// THIS FOLLOWS A SYMBOLIC LINK AND DOES NOT REFUSE ONE. fs.Stat resolves a
// link, so a link named borrowed that points at a directory reads as a
// quarantine here and its target is stated to be inside the experiment by
// nothing. That is deliberately not repaired at this site: a link anywhere
// under experiments/ is already refused by the stray-record walk, which reads
// the entry rather than the target, and a second rule deciding what a link
// points at is the resolution that walk exists to avoid.
func isDirectory(fsys fs.FS, name string) (bool, error) {
info, err := fs.Stat(fsys, name)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return false, nil
}
return false, err
}
return info.IsDir(), nil
}

// isRegularFile says whether a name in the walked filesystem is a file a reader
// can open. A licence that is a directory, or a link, is not one, and it is the
// same answer as a licence that is not there: in both cases nothing at that
// path states terms.
func isRegularFile(fsys fs.FS, name string) (bool, error) {
info, err := fs.Stat(fsys, name)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return false, nil
}
return false, err
}
return info.Mode().IsRegular(), nil
}
11 changes: 8 additions & 3 deletions internal/check/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -524,14 +524,19 @@ func walkExperiments(fsys fs.FS, root string, res *Result) error {
res.Refusals = append(res.Refusals, refuseMeasurementCommit(record, data)...)
res.Refusals = append(res.Refusals, refuseDates(record, data, res.Now)...)
res.Refusals = append(res.Refusals, refusePromotion(record, data)...)
// The only rule here that reads the directory as well as the record,
// which is why it takes both and why it can fail: the others judge
// bytes already in hand and this one walks.
// The two rules here that read the directory as well as the record,
// which is why they take both and why they can fail: the others judge
// bytes already in hand and these two walk.
hardwareRefusals, err := refuseHardware(fsys, experimentPath, experiment, record, data)
if err != nil {
return err
}
res.Refusals = append(res.Refusals, hardwareRefusals...)
borrowedRefusals, err := refuseBorrowed(fsys, root, experimentPath, record, data)
if err != nil {
return err
}
res.Refusals = append(res.Refusals, borrowedRefusals...)
if parsed, err := ParseRecord(data); err == nil {
seen.slug, seen.declaresSlug = parsed.Field(FieldSlug)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
directories 1
records 1
experiments present
decisions absent
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
borrowed-directory-carries-no-licence
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
an-experiment-that-borrows-and-declares-it
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Slug: one
State: asking
Question-Written: 2026-01-01
Needs-Hardware: none
Borrowed: the reference implementation from example.invalid, under the MIT licence

## 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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The borrowed implementation would sit here.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
directories 1
records 1
experiments present
decisions absent
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
record-borrowed-declaration-names-no-directory
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a-record-that-declares-no-borrowing
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Slug: one
State: asking
Question-Written: 2026-01-01
Needs-Hardware: none
Borrowed: the reference implementation from example.invalid, under the MIT licence

## 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
4 changes: 4 additions & 0 deletions testdata/cases/a-record-that-declares-no-borrowing/expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
directories 1
records 1
experiments present
decisions absent
Empty file.
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
directories 1
records 1
experiments present
decisions absent
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Slug: one
State: asking
Question-Written: 2026-01-01
Needs-Hardware: none
Borrowed: the reference implementation from example.invalid, under the MIT licence

## 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
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The borrowed implementation would sit here.
Loading