8.2 KiB
8.2 KiB
Rules
- Go runs only through
docker compose run --rm <test|vet|fmt|build|cyclo|generate>; the merge gate isdocker build .plus CI's changelog check. - Tests first, in their own commit; the implementation follows in the next. A re-pin of seeded output or of
testdata/shipped_shape.txtis its own commit. - A change under
data/or to the shape pin adds itsCHANGELOG.mdentry underUnreleasedin the same PR, and so does a change to a flag, an exit code, an exported name, a fence, a builtin or the lowest Go; what is major is the README's Versioning table. - One-line commit messages: no ticket prefix, no repo name, no authorship trailers.
- GitHub is where the project lives, so
ghis the tool: merges are fast-forward only,gh pr merge --rebasewhere the branch is already on top of main. - CodeRabbit skips every pull request until the repository has 10 GitHub stars: check its status once when a PR is marked ready, answer a review if one is there, and never wait for one.
- README goal 3 is gated at 7.0 on the
comprehension-panelskill, and below it nothing else merges — no feature, no category, no data — bar a security fix, a dependency bump, a repair of behaviour the README documents, and the infrastructure the round itself runs on.todo.mdcarries the round: a PR per item it plans, the nine-seat findings at depth 1 or a restructure the maintainer approved, then the nine-seat run again, until the score passes. At or above 7.0 every pull request scores with the four-seat run and answers it in one run. No merge lowers the last score its own panel recorded: the nine-seat round and the four-seat run are two ratchets, never compared with each other. A lower score blocks the merge even where it may be panel noise: fix what the seats name until the score rises. - Hard tabs. No comment by default; delete a restatement, a rationale, history, or a file preamble.
- Prose naming a source states what that source states: read the register's own field before paraphrasing it, and name the register you read before claiming none publishes a spelling.
- A README example is a
jsonblock that loads and renders as a category;readme_test.goruns every one. - Cyclomatic complexity is gated at 14: split a function that would go over it. A table-shaped dispatch, a switch with one case per kind of its input, may sit at 14 and stays whole.
Decisions
- GitHub is canonical, and the module path names it
- The Gitea copy stays, as a pull mirror of GitHub
- The vocabulary sits below
doc.go's package clause, not in the package doc - Options and fields share one namespace
{a|b}stays beside nested choices- Flags follow getopt_long
- An argument is a template by its shape, not by a flag
- An inline template that does not compile is misuse (exit 2), including a reference that resolves to nothing
- A padded JSON argument is rejected, not trimmed
FakeTemplateandNewTemplateboth stay- The shipped data is embedded, not discovered
- With only the shipped set, a category loads on the first call reaching it; beside a
--data-path, every category loads inNew - Every
{…}draws afresh, and only a name keeps a pick - Reference sigils follow the filesystem
- A change to what exists is a major; a minor only adds
- An error is a contract by what it names, not its bytes
- A load reports every mistake at once
- Formats are checked after all data is loaded, so their errors name the category
- Raising the lowest supported Go is a major
- The format check runs on the latest Go only
- The changelog heading is the one spelling of a release; CI cuts the tag
- A
--data-pathoverride rebinds every reference to the category it replaces - The repeat cap bounds renders, not bytes
- 64-bit targets only
- A constant zero divisor is a load error; in a string column a divisor that is not constant prints
Inf - In data, a default written out and a constant spelled as a sample are load errors
- 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 record's column set is fixed before the first draw
- Null is a
nullitem, not a rate - A typed column holds one value, not composed text
- A column that only reads one reference or name is the column it reads
- A typed column's calc is refused unless proven
Columncarries text, not a Go value- A unit takes the stem of what it is, and a file the stem of the units it holds
- One name, one meaning
- The performance gate asserts allocations, not wall-clock time
- Rows live in a TSV, the shape in JSON
- A selector is bracketed, and a dot inside it is literal
parentnames the link column and the table alike- After a row, a path names a column or a linked table
- A selected row is fixed, not drawn
..steps up to the parent row, and a step down after it draws afresh, or once per name's pick- A table selects by one key column, a code, never a free-form name
- A parent row with no child row is a load error
- The choice-of-rows fence guards a data file's root, and requires string fields
- A table is a record of string columns
- The key map is built at load, the rest on first draw
- Two categories may name one TSV
- A cell may read a reference, and each row its own
- A path is walked once without drawing before it is walked for real
- A country's postal codes and streets are siblings under its locality
- A locale's
addressreads its country'sgeotree, so a locale folder is no data set on its own - The default embed holds every Swedish postort the import can place and give a street-delivery code and a street, and the US places of 25,000 or more
- A locale's
addressbinds its country's record once and prints it whole - A postort's kommun comes from its name, its tätort or its codes, never from distance
- A highway designation is not a street, and a US postal code belongs to the place holding most of its land inside places
--liststays a plain list of paths- A layout is always quoted
- A title is a table under
sex - A table owns the spelling of a selector on it
- No builtin reads the clock, so a date is bounded by days, never by an age
miscis what every locale shares- A register's canonical spelling loses to the one its domain writes
misc.territoryis the spine, and amisctable naming a territory links to it- A table whose register publishes no frequency draws evenly
misc.timezoneweighs a zone by the people living in itmisc.caris one flat table, not a make linked to its modelsmisc.territorynames its sovereign in a column, and there is nomisc.countrytablemisc.loglevelis a table keyed by the syslog code, and named by POSIX's keywordmisc.tldkeys carry the leading dot, where other tables key on a bare codemisc.tldis a table of its own, andmisc.territory.tldstays a columnmisc.territorycarries a currency code, it does not link tomisc.currency- An extension may name two media types
- The Swedish ids draw Skatteverket's test series
- The US given names come from a mirror of the SSA file
Listadvertises direct descents only- A path draws through its compiled steps
- A name lives in the category binding it, or in the repeat binding it, and is drawn on its first read
- comprehension floor: every dimension and the overall at 7.0 or above
- The template engine stays the root package until item 107; what reads no engine type, a table's rows included, sits in
internal/ - Goal 5.1's
{…}covers{{,}}and a lone}, so the goal names no escape - Goal 7.2 holds while a first template can be written with no escape; a literal brace still takes
{{or}}
Scoring run
The project values for ~/.claude/skills/comprehension-panel/scoring-run.md:
{language}: Go{kind}: a Go library and CLI that renders fake data from JSON templates{domain}: fake test-data generation and template languages{domain docs}: the documentation of any fake-data library, such as Faker{3am question}: a seeded render ofsv_SE.addressprints the postal code of one postort beside a street of another