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: 20 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,26 @@ heading-aliases: Concepts <=> Wire form; Determinism / Stability Contract <=> St

"Testing" is not a single line saying "tests exist". It must let the reader judge **trustworthiness**: list the specific property each test guards, the coverage number, and whether `vet`/`-race` pass, plus reproduction commands. If a function is left uncovered, state why explicitly.

### Experimental: evidence anchors (pilot)

A contract-level entry (e.g. a Public API or Stability Contract entry) may
carry an **evidence anchor** — a backticked
"path::symbol" reference (file + symbol, **never a line number**: line
numbers drift on every edit; symbol names are stable and their existence is
grep-checkable, the same granularity as the test-name and exported-symbol
checks). `scripts/check-docs.sh` check 8 keeps written anchors valid: the
file must exist and declare the symbol (function, method, or
`type`/`const`/`var`). Anchors are **opt-in** — the check never requires
writing one; it only stops contract prose from silently outliving the symbol
it describes.

Status: **pilot**, currently only in `docs/fetch.md` (see the `Anchor:`
sentences there for live examples) — evaluating signal-to-noise before any
wider adoption. Promotion to a repository-wide convention, if it happens,
goes through an ADR. Point-in-time historical claims anchor a commit SHA
instead of a live symbol — frozen is a feature there. ADR bodies never carry
live anchors (see `docs/adr/README.md`).

## Running the tests locally

DART has no external dependencies, so the standard commands are all that is
Expand Down
7 changes: 5 additions & 2 deletions docs/fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type HTTPFetcher struct {
or the wrong offset would otherwise have its bytes cached under the block's
key, and the block cache is write-once per key, so that corruption would be
permanent. `Content-Range` is also parsed for `Total`.
Anchor: `internal/fetch/fetch.go::Fetch`.
- If the origin **ignores** the Range and returns `200`, the window is sliced
out of the stream **without buffering the whole object**: bytes before `start`
are discarded, at most `end-start+1` are read, and the rest of the response is
Expand Down Expand Up @@ -95,6 +96,7 @@ Range-ignoring origins. Time complexity is O(1); no body bytes are buffered.
starts a new one (the fix for issue #4's permanently-poisoned cache key: a
stalled flight expires instead of blocking the key forever). Joiners of a
flight wait inline, one worker goroutine per flight (#60).
Anchor: `internal/fetch/fetch.go::DefaultMaxFlight`.

### 3.4 `func FetchBlock(ctx, f Fetcher, url string, blockSize, blockIndex, size int64) (Range, error)`

Expand All @@ -116,7 +118,7 @@ index whose start multiplication or end addition would overflow — is an
**error before the fetcher is invoked**: a wrapped start would otherwise
recycle to 0 (silently fetching block 0's bytes) or go negative, which
`HTTPFetcher.Fetch` reads as "no Range header" — a one-block fetch degrading
into a whole-object GET.
into a whole-object GET. Anchor: `internal/fetch/fetch.go::FetchBlock`.

### 3.5 `type Coalescing`

Expand All @@ -137,6 +139,7 @@ first) the flight becomes **stale**: a caller still waiting re-checks, evicts
the stale entry, and leads a replacement; a late-finishing stale leader never
deletes the replacement's entry. Without the bound, one half-dead origin
connection would poison the cache key for the process lifetime.
Anchor: `internal/fetch/fetch.go::acquire`.

A flight keeps **exactly one worker goroutine** — started by whoever leads it —
no matter how many callers join or abandon it: joiners wait inline on the
Expand All @@ -155,7 +158,7 @@ not still waiting for it (the engine's size probe relies on this: a failed
probe is re-issued against origin, never served twice — issue #69). The mirror
cost: a caller arriving in the window between removal and publication leads a
duplicate fetch instead of sharing the just-finished result — bounded extra
traffic, by design.
traffic, by design. Anchor: `internal/fetch/fetch.go::finish`.

Each caller's own `ctx` only bounds how long that caller waits (a cancelled
caller returns `ctx.Err()`).
Expand Down
35 changes: 35 additions & 0 deletions scripts/check-docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,22 @@
# (modulo leading indentation)
# 7. every non-superseded ADR is referenced by number from current law
# (docs/*.md or AGENTS.md, excluding docs/adr/)
# 8. evidence anchors: backticked `path::symbol` references in docs/*.md
# resolve — the file exists and declares the symbol (opt-in anchors;
# pilot convention, see docs/README.md)
#
# Plus one warning (never fails): relative .md links that point nowhere.
#
# This is a FLOOR check: it guarantees presence and lockstep, not quality or
# semantics. Known limits: check 3 covers single-line const/var declarations
# and methods, not grouped const members without individual doc comments, and
# a symbol only appearing in example code still counts as "documented";
# check 8 likewise matches only single-line declarations (func/method/type/
# const/var), not grouped const members — anchor individually declared
# symbols; check 8 sees that a declaration exists, never that the anchored
# prose describes it correctly, and its greps are not comment-aware (a
# `type Foo` inside a comment would satisfy it — same class of limit as
# check 3's example-code caveat).
# check 4 matches required words at non-letter boundaries in heading text
# (first-word aliases included), so "## Instability notes" does not satisfy
# Stability but "## 6. Determinism / Stability Contract" does; check 7 sees
Expand Down Expand Up @@ -251,6 +260,32 @@ for f in docs/adr/[0-9][0-9][0-9][0-9]-*.md; do
done
ok "check7: ADR back-references"

# ---------------------------------------------------------------- check 8
# Evidence anchors: backticked `path::symbol` references in docs/*.md must
# resolve — the file exists and declares the symbol. Anchors are opt-in: the
# check never requires writing one, it only keeps written anchors valid, so
# contract prose cannot silently outlive the symbol it describes. No line
# numbers, by design: symbol names drift far less than lines, and existence
# is grep-checkable — the same granularity as checks 2/3.
for doc in docs/*.md; do
anchors=$(grep -oE '`[A-Za-z0-9_/.-]+::[A-Za-z_][A-Za-z0-9_]*`' "$doc" | tr -d '`' | sort -u)
while IFS= read -r a; do
[ -z "$a" ] && continue
af=${a%%::*}; as=${a##*::}
if [ ! -f "$af" ]; then
err "check8: $doc anchors \`$a\`, but $af does not exist"
continue
fi
# func/method: func Symbol( or func (recv) Symbol(
# otherwise: type|const|var Symbol<boundary>
if ! grep -qE "func +(\([^)]*\) +)?$as\(" "$af" \
&& ! grep -qE "(type|const|var) +$as([^A-Za-z0-9_]|\$)" "$af"; then
err "check8: $doc anchors \`$a\`, but $as is not declared in $af"
fi
done <<<"$anchors"
done
ok "check8: evidence anchors resolve"

# ------------------------------------------------- link warning (soft)
for doc in docs/*.md docs/adr/*.md AGENTS.md CONTRIBUTING.md README.md; do
[ -f "$doc" ] || continue
Expand Down
Loading