From c68f571867a419d3b1f9ce9a94a9caee951f7306 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Thu, 8 Oct 2026 11:46:47 +0200 Subject: [PATCH] Let a category reference itself and blank stdin render, rest the typed column on goal 6.1, and drop item 47 and item 46's unnamed rows files --- AGENTS.md | 2 +- docs/decisions.md | 19 +++++++++---------- todo.md | 11 +++-------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8a3f42c..06892d9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -64,7 +64,7 @@ In [docs/decisions.md](docs/decisions.md): - Samples say what they emit, transforms what they do - A record is a template seen as columns; a Go struct is the one second schema - A struct's records follow Go's field access, and compile on first use -- A category never references itself, and a record's fences run at load +- A category may reference itself, and a record's fences run at load - A record's column set is fixed before the first draw - Null is a `null` item, not a rate - A typed column holds one value, not composed text diff --git a/docs/decisions.md b/docs/decisions.md index afad4d1..3cdcdd1 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -83,8 +83,7 @@ adding one: a rule a user states in one sentence, at the cost of `printf` or a A JSON template is its JSON, so the whitespace around it is no part of the template, per the decision "Whitespace around a JSON template is dropped, in `NewTemplate` and on -stdin". Stdin holding only whitespace is misuse, since an unset variable sends just a -newline. +stdin". Stdin holding only whitespace is a template like any other, and renders it. A lone reference, `{/users}` or `"{/users}"`, names the record `users` under `--format`, one newline after it allowed, with `users` the default `--table`; one to nothing there @@ -339,15 +338,14 @@ caller's types, so the first `FakeStruct` for a type compiles its tags and the a error included, is kept per type: a test's first call is its load, and no `NewStruct` handle is needed, as the cache already compiles once. -## A category never references itself, and a record's fences run at load +## A category may reference itself, and a record's fences run at load -2026-09-16, Lilleman auf Larv. +2026-09-16, Lilleman auf Larv; revised 2026-10-07. Serves goals 5.2 and 5.7. -A category is one unit: a reference back into it — `{/users.first}` inside `users` — -describes a draw other than the fields beside it, so `New` refuses it and the sibling -field stays the one spelling for a field of one's own. A value two fields share goes in its -own category, which one field binds to a name and both read (goal 4.1). That settled, a record's column fences -run at `New` too, so a category that loads renders as a value and as a record alike. +A reference back into a category, `{/users.first}` inside `users`, is a fresh draw, as +every `{…}` is; only a cycle is refused. A value two fields share goes in its own +category, which one field binds to a name and both read (goal 4.1). A record's column +fences run at `New` too, so a category that loads renders as a value and as a record alike. ## A record's column set is fixed before the first draw @@ -370,7 +368,8 @@ null renders `""`. ## A typed column holds one value, not composed text -2026-09-15, Lilleman auf Larv. +2026-09-15, Lilleman auf Larv. Serves goal 6.1: a typed column's values are proven valid at +load, and composed text is not proven. Its bounds come from a literal or a call's arguments, so a load error names a real value and a range check is one comparison: `1{digits(2)}` is refused in a typed column, diff --git a/todo.md b/todo.md index fd296d7..be46caf 100644 --- a/todo.md +++ b/todo.md @@ -117,7 +117,7 @@ | 42 | 0.2.0 | | **Refuse a struct tag's `datatype` naming the Go type that sets it before proving its values, as the README's Library section promises.** | 2 | 2 | 4 | 6 | 6 | 14.5 | | 32 | 0.2.0 | | **Add `misc.browser` as the parent of `misc.useragent`, so `misc.browser[Chrome].useragent` resolves.** | 3 | 3 | 4 | 6 | 4.1 | 14.4 | | 22 | 0.2.0 | | **Give `url` and `email` a path that draws only domains nobody can register, keeping the wide set as the default.** | 3 | 4 | 7 | 8 | 16 | 14.0 | -| 46 | 0.2.0 | | **Report the same error every load for a table with two bad options, and for a folder with two unnamed rows files.** | 2 | 2 | 3 | 7 | 6, 10 | 14.0 | +| 46 | 0.2.0 | | **Report the same error every load for a table with two bad options.** | 2 | 2 | 3 | 7 | 6, 10 | 14.0 | | 158 | 0.2.0 | | **Drop a UTF-8 byte order mark that starts stdin, and say in the README how to stop PowerShell 5.1 sending `Göteborg` as `G?teborg`.** | 2 | 2 | 4 | 5 | 7.2, 5.1 | 13.5 | | 79 | 0.2.0 | decision | **Beside a `--data-path`, load in `New` the user's categories, the shipped ones they override or read, and the shipped ones whose reads reach an overridden one; load the rest on first reach.** | 6 | 6 | 7 | 8 | 13 | 12.9 | | 27 | 0.2.0 | | **Merge `en_US.ip` and `sv_SE.ip`, today byte-identical, into one `misc.ip`.** | 3 | 2 | 4 | 6 | 8 | 12.3 | @@ -141,7 +141,6 @@ | 23 | 0.3.0 | | **Give every other shipped category that could reach something real a path that never does.** | 3 | 6 | 6 | 7 | 16 | 11.0 | | 75 | 0.3.0 | | **Run every README `sh`, `go` and `text` example as a test, and compare each "Renders" line to a seeded render.** | 2 | 6 | 4 | 7 | 12.2 | 10.8 | | 33 | 0.3.0 | | **Group `data/misc` into folders where a group name makes a path easier to guess.** | 4 | 5 | 4 | 5 | 5 | 10.8 | -| 47 | 0.3.0 | defect | **Refuse a category naming a hidden rows file, `"rows": ".x.tsv"`, as a rows file that is not there.** | 1 | 1 | 2 | 5 | 6 | 10.2 | | 72 | 0.3.0 | principle | **Fail the merge gate when test coverage falls below the last recorded figure.** | 2 | 3 | 2 | 5 | 3 | 10.2 | | 30 | 0.3.0 | | **Draw `email.local` from `username`, so the two share one handle list.** | 2 | 2 | 3 | 5 | 8 | 10.0 | | 95 | 0.3.0 | principle | **Hold a struct's columns and the field each fills in one slice.** | 1 | 2 | 1 | 5 | 3.2 | 9.5 | @@ -444,9 +443,9 @@ Require the path step to reach a sibling category. 17 of the 40 distinct ones shipped today sit on `.se`, `.nu`, `.io` and `.co`, which anyone may register, and only RFC 2606's `example.com`, `.net`, `.org`, `.test`, `.example`, `.invalid` and `.localhost` provably reach nothing. -### 46. Report the same error every load for a table with two bad options, and for a folder with two unnamed rows files. +### 46. Report the same error every load for a table with two bad options. -`readTableOptions` in `table.go` and `walkDir` in `internal/datafiles` return on the first in Go's map order. +`readTableOptions` in `table.go` returns on the first in Go's map order. ### 158. Drop a UTF-8 byte order mark that starts stdin, and say in the README how to stop PowerShell 5.1 sending `Göteborg` as `G?teborg`. @@ -526,10 +525,6 @@ Both phone formats carry the same 21-code `area` list, so an edit to one copy ca `readme_test.go` loads and renders each `json` block, but runs no `sh` example (CLI, Records, Table, Linked tables), no `go` example (Library) and no `text` block of error text, and compares no "Renders e.g." output, so goal 12.2 is not met. -### 47. Refuse a category naming a hidden rows file, `"rows": ".x.tsv"`, as a rows file that is not there. - -`internal/datafiles` indexes hidden TSVs in `newRowsFiles` and skips them in `walkDir`, so one loads where its comment says a hidden file is never data. - ### 72. Fail the merge gate when test coverage falls below the last recorded figure. `technical-principles.md` holds that test coverage should not decline. `docker compose run --rm cover` prints the figure, and neither the `Dockerfile` gate nor `.github/workflows/test.yml` checks it.