Commit Graph

143 Commits

Author SHA1 Message Date
lilleman ae0527a26e Tests for the real data-path error, an empty data path, and a crypto/rand failure
Tests / vet + fmt + tests (pull_request) Failing after 16s
2026-09-02 19:09:19 +02:00
lilleman 4f9285ab5c Reject non-finite float bounds, unplain integer args, constant samples, a constant zero divisor and the default separator; a binding key is no path segment; ascii keeps DEL; an unheld path panics
Tests / vet + fmt + tests (pull_request) Successful in 56s
2026-09-02 19:08:32 +02:00
lilleman 7b28dc36d9 Tests for finite float bounds, plain integer args, constant samples and divisors, the default separator, binding keys in paths, DEL in ascii, and an unheld path
Tests / vet + fmt + tests (pull_request) Failing after 42s
2026-09-02 19:08:24 +02:00
lilleman 3d3efbb642 Bound --repeat at MaxRepeat and stream the renders; name an unknown flag by its rune; --list rejects an inert --repeat or --separator
Tests / vet + fmt + tests (pull_request) Successful in 56s
2026-09-02 19:06:20 +02:00
lilleman 5a75df8034 Tests for a bounded, streamed --repeat, rune-named flags, and --list with inert flags 2026-09-02 19:06:15 +02:00
lilleman fdbbf94d2c Compare and cache a read by its one spelling, so two spellings of one reference are one level; reject a slash after a sigil naming the spelling
Tests / vet + fmt + tests (pull_request) Successful in 55s
2026-09-02 18:45:31 +02:00
lilleman 512696722d Tests for two spellings of one reference being one level, and a slash after a sigil
Tests / vet + fmt + tests (pull_request) Failing after 38s
2026-09-02 18:45:21 +02:00
lilleman 1b8768e431 Record the compatibility policy, the override consequence and the deferred data de-duplication
Tests / vet + fmt + tests (pull_request) Successful in 55s
2026-09-02 18:32:11 +02:00
lilleman f9647ff6bb Decompose compileTemplate, checkBoundLevelsHeld and loadDir; gate cyclomatic complexity at 14
Tests / vet + fmt + tests (pull_request) Successful in 54s
2026-09-02 18:31:38 +02:00
lilleman bcbf044290 One path walk under checkPath, descend, readField, pathLeaves and coverPath; split the hold and the render graph into their own files
Tests / vet + fmt + tests (pull_request) Successful in 53s
2026-09-02 18:29:45 +02:00
lilleman 7581587a19 Tests for the path walk; test files named for the modules they exercise
Tests / vet + fmt + tests (pull_request) Failing after 14s
2026-09-02 18:29:36 +02:00
lilleman 1bf5470c6f Reference sigils follow the filesystem: / the root, . this folder, .. the folder above
Tests / vet + fmt + tests (pull_request) Successful in 53s
2026-09-02 18:26:02 +02:00
lilleman 5d1e567b8d Tests for reference sigils: / the root, . this folder, .. the folder above 2026-09-02 18:25:55 +02:00
lilleman 1b1b93b35f Reject weight 0, a never-numeric calc operand and a repeat product past the cap; the CLI classifies ErrNoData
Tests / vet + fmt + tests (pull_request) Successful in 52s
2026-09-02 18:23:03 +02:00
lilleman 34c933b2b3 Tests for weight 0, a never-numeric calc operand, the repeat product along a path, and ErrNoData 2026-09-02 18:22:55 +02:00
lilleman c5c06375d8 Reject a repeated bare token of a held name, naming the single-token spelling
Tests / vet + fmt + tests (pull_request) Successful in 53s
2026-09-02 18:21:03 +02:00
lilleman 5514b42b7b Tests for a repeated bare token of a held name 2026-09-02 18:20:57 +02:00
lilleman 88e71e666d Delete the grammar converters; their output is committed and re-running them corrupts it
Tests / vet + fmt + tests (pull_request) Successful in 53s
2026-09-02 18:18:07 +02:00
lilleman 0ad88028c4 One path reads a flag's value: short flags attach and bundle, = after one is rejected naming the spelling
Tests / vet + fmt + tests (pull_request) Successful in 52s
2026-09-02 14:09:48 +02:00
lilleman f6782cf477 Tests for attached and bundled short flags, and = after a short flag 2026-09-02 14:08:58 +02:00
lilleman 8cd603a2b1 Key the repeated-item check on the string itself; marshal only objects
Tests / vet + fmt + tests (pull_request) Successful in 51s
2026-09-02 12:59:12 +02:00
lilleman 00a6160aa4 Restructure the README around the grammar, record the standing decisions, add the contributor rules 2026-09-02 12:56:11 +02:00
lilleman 035e51d3e1 Tests that the README examples load, render and print what they claim 2026-09-02 12:53:29 +02:00
lilleman 31c2f12098 Hold a reference path like a sibling path; add the lowercase, uppercase and ascii transforms 2026-09-02 12:52:19 +02:00
lilleman 8fa33694b9 Tests for references held like siblings and the lowercase, uppercase and ascii transforms 2026-09-02 12:52:12 +02:00
lilleman f0305f191f Re-pin the seeded outputs now that a one-item choice draws nothing 2026-09-02 12:39:04 +02:00
lilleman 054f99c94f One spelling per shape: reject a one-item choice, a repeated item and an inert object; reshape the data 2026-09-02 12:38:59 +02:00
lilleman de8c1d13e9 Tests for one spelling per shape: no one-item choice, repeated item or inert object 2026-09-02 12:38:07 +02:00
lilleman ff4b243148 Format text is literal; class runs are {digits(n)} {upper(n)} {lower(n)}; a string is a format 2026-09-02 12:37:21 +02:00
lilleman 99d8aa0fb7 Tests for literal format text, brace escapes and the class builtins 2026-09-02 12:28:51 +02:00
lilleman f210c7a764 Embed the shipped data, load any fs.FS, New takes options, Fake is safe for concurrent use 2026-09-01 23:07:15 +02:00
lilleman 91cbae2a44 Tests for the shipped data layer, New options and concurrent Fake 2026-09-01 23:05:58 +02:00
lilleman cf9de21495 GNU-style flags: --name, short aliases, any position, help on stdout 2026-09-01 23:02:19 +02:00
lilleman f773738243 Tests for GNU-style flags 2026-09-01 23:02:17 +02:00
lilleman 5576a9e05e Drop the stale kind count from the builtins registry comment
Tests / vet + fmt + tests (pull_request) Successful in 25s
Tests / vet + fmt + tests (push) Successful in 6s
2026-09-01 21:45:45 +02:00
lilleman 5d33f4c0f0 Rename the builtin kind from generator to sample
Tests / vet + fmt + tests (pull_request) Successful in 32s
2026-09-01 21:41:35 +02:00
lilleman 04b7b6a432 Rename the exported type to Generator and retire the faker wording
Tests / vet + fmt + tests (pull_request) Successful in 25s
2026-09-01 21:34:27 +02:00
lilleman d44c941a92 Make the CI gate work on Gitea by building instead of bind-mounting
Tests / vet + fmt + tests (pull_request) Successful in 27s
Tests / vet + fmt + tests (push) Successful in 6s
2026-09-01 20:33:04 +02:00
lilleman 05dc042e49 Rename the project to fejkdata and record the fork source
Tests / vet + fmt + tests (pull_request) Failing after 6s
2026-09-01 20:24:03 +02:00
M 64a0d29496 Say why an empty name is rejected, and finish what that removed
Tests / vet + fmt + tests (push) Failing after 42s
The reason given was wrong. A dot path did reach an empty-named field:
Fake("a.") returned it, Fake("a.b.") returned a nested one, and {..a.} bound
it. What was true is narrower — List never offered it, because an empty name
is no path segment — so the engine accepted spellings it would not advertise.
The message, the test comment and the README say that instead.

Two things the rejection finished off:

A {} token still reported "no field \"\"", pointing at a fix the loader now
rejects — two errors for one rule. It is told the name can never exist, like
an option token already is.

addressable is dead: both halves of "not empty and no dot" are now rejected
where a name is authored. Mutating it to panic leaves the suite green here
and panics on main, so it was live and is not. Keeping it would preserve the
silent-hiding this change removes — List quietly omitting a name rather than
New refusing it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 07:31:18 +02:00
M 138bd21d83 Reject an empty field name
A field named "" was reachable by exactly one spelling, a bare {} token,
and by no dot path: List hid it and Fake could not ask for it. checkName
rejects it now, for the reason it rejects a dot — a name no path can reach.

That also makes the empty-segment rule unconditional. {a.} was rejected
because a field really named "" would otherwise have made it resolve; no
data can carry one, so the rule now guards a shape that cannot exist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 07:31:18 +02:00
M e31e77b8a3 Tests for an empty field name
A field named "" loads, and a bare {} token renders it, but no dot path can
reach it — List hides it and Fake cannot ask for it. {a.} is already rejected
for the same reason, so the two spellings disagree about the same mistake.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 07:31:18 +02:00
M 4b3dd011fc Pin the per-head walk, and say where the hold stops
Sharing renders' seen set across heads left the suite green while silently
under-rejecting: the first head's walk marks the only route to the second
head's draw. This PR widens heads from the bound levels to every held name,
so two heads in one template is now the ordinary case; a rejected case whose
violation sits on the later head pins the scoping.

An operand rendering one field twice covers the revisit guard, taking
coverage to 97.8% against main's 97.4%.

The README said the two spellings are rejected alike without saying what the
hold follows, which is not true where the operand reaches its own field
through a reference. It now names the plain {field} tokens the walk follows.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 21e7af6c1f Hold what a calc operand's render settled, up to a reference
The fence pinned only the operand node, so a reference reaching into it drew
that value again: {net.v} was a load error while {..cat.net.v} loaded and
disagreed in 20 of 40 renders. The hold now covers what rendering the operand
settles inside itself, so both spellings of that shape are rejected.

The walk stops at a {..path} edge, where the operand's own value ends and a
shared source begins. cover stops there too, through named, so both halves of
the fence end at the same boundary — and two names drawing from one referenced
category stay two draws.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 8d03ce34bb Tests for a reference reaching into a calc operand
{net.v} is a load error because the operand is also a path head, but
{..cat.net.v} names the same node by another spelling and loads — and
disagrees in 20 of 40 renders. Same shape, opposite verdicts, which is the
thing this rule exists to remove.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M cf3229cd4d Pin the route an operand fence names
The operand label had no test: every rejected case reported through a token
edge, so flipping the flag that distinguishes the two left the suite green
while the error went back to inventing a {b} the format never wrote. Each
case now asserts the route it names, and one reports through an operand edge,
which is the branch that was uncovered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 39d59aec23 Pin the prep-time guards, and say why an operand's set is the narrow one
The guards report an invariant break instead of computing around it, and no
data reaches them, so they are called directly: coverage 97.4% -> 97.7%,
which also covers the empty-cover skip through a literal operand.

operandDraw's doc keeps why neither wider set works, since both were tried
here — containment reaches a sibling the operand never renders, the render
closure reaches a source two operands share — and drops the rest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M f949550515 One spelling for an unvalidated builtin arg, and say what the hold buys
float's prep still swallowed ParseFloat's error three lines from the atoi that
had just been changed to report one — two spellings of "parse an arg the check
already validated". atof reports it the same way.

The README paragraph said a reference reaching through an operand is caught,
which the narrowed fence no longer does and should not: it says what the hold
pins instead. Restored the why the trimmed comment in expand had carried.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 027d5c33fc Name a calc operand as one when the fence reports it
A renderEdge label can be an operand name, and both messages printed it as
{name} — so an author was told a token renders the level when no such token
existed in the format. An edge now carries whether its label is an operand and
names itself the way boundReaders does, so both fences speak one language.

The narrowed operand cover fixed the other half: the render closure pulled the
other operand into the cover, which could report the two sides the wrong way
round ({n} renders "m" where it is m that reaches n).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 3f46e9c701 Tests for what a calc operand's hold actually pins
A calc renders its operand whole, so the draw it holds is that one node's
value. The render closure was too wide: it pulled in shared descendants, so
two operands drawing from one source were rejected — two dice over one
{..die}, or {w} x {h} over one {..dim} — though each is drawn once, shown
once, and cannot disagree. main accepts all of them.

So the fence is another route naming the operand's own node, and these pin
both sides: a reference to the operand, one level down, or wrapped in a
choice is rejected; two names drawing from one source, a sibling the operand
never renders, and a literal operand are accepted. That reverses the case
added earlier this round, which read a shared source as a second spelling.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00