docs: codify feature-acceptance criterion (LLM-author utility)

Adds DESIGN.md "Feature-acceptance criterion" as a top-level section:
a feature ships only if (1) an LLM author naturally produces code
that uses it, and (2) it measurably improves correctness or removes
redundancy. Aesthetic appeal and human ergonomics do not count.

Mirrored in CLAUDE.md as "Feature acceptance: LLM utility", paired
with the existing "Design rationale != implementation effort". The
two together narrow valid feature rationales to one thing: what the
LLM author gets out of the feature.

Trigger: the typeclass-design conversation around 22a. Rule was
implicit in many past decisions (Decision 1's JSON-over-text choice,
Decision 10's "what LLMs are good at" reasoning) but never stated
as a feature-gate. Codifying it now means future feature proposals
get evaluated against an articulated criterion instead of being
re-derived each time.

Documentation-only; no Rust, schema, or bench changes. Test state
288/0/3 unchanged.
This commit is contained in:
2026-05-09 10:59:28 +02:00
parent aea3758742
commit 338a4cd3fe
3 changed files with 138 additions and 0 deletions
+13
View File
@@ -90,6 +90,19 @@ locality (modes belong to fn-parameter positions, not to types in
general), and I retroactively had to add it. JOURNAL entries from
2026-05-08 record the lesson.
### Feature acceptance: LLM utility
When deciding whether a proposed feature ships, the test is
whether an LLM author naturally produces code that uses it AND
whether the feature measurably improves correctness or removes
redundancy. Aesthetic appeal does not count; neither does human
ergonomics. The full criterion lives in DESIGN.md
("Feature-acceptance criterion").
This is the positive complement to the rule above. Together they
narrow the space of valid feature rationales to one thing: what
AILang's actual user — the LLM author — gets out of it.
### Direction freedom
I have authority to choose the next iter, refactor, or feature
+42
View File
@@ -61,6 +61,48 @@ everything that lands in git is English. This keeps diffs and tooling output
uniform and matches the audience for AILang (LLM authors), for whom English
is the default.
## Feature-acceptance criterion
A proposed feature ships only if both hold:
1. **An LLM author naturally produces code that uses it.** Without
prompting toward the feature, the LLM reaches for it as the clean
way to express the situation. If the feature is only used when
explicitly mentioned, it isn't earning its keep — the LLM is the
only author, and what the LLM doesn't reach for naturally is dead
surface area.
2. **The feature measurably improves correctness or removes
redundancy.** Either it eliminates a class of bugs structurally
(the schema forbids the wrong code), or it lets the LLM express the
same logic in fewer sites that have to stay consistent across
edits. Aesthetic appeal — "feels elegant", "is idiomatic" — does
not count.
This is the positive complement to the CLAUDE.md rule that
implementation effort is not a rationale: cost is not a reason *for* a
feature, and neither is human aesthetic preference. The only thing
that is, is LLM-author utility.
Two corollaries:
- **Human-attractive but LLM-neutral features are cut.** Point-free
style, operator overloading, implicit conversions, syntactic
shortcuts that hide structure. They reward human authors who enjoy
compression; they cost the LLM the explicit form it relies on to
keep RC, uniqueness, and effects locally legible.
- **Human-hostile but LLM-friendly features are kept.** JSON as
canonical authoring surface; mandatory mode annotations on every
fn parameter; mandatory top-level type signatures; explicit `clone`
for shared values. These cost a human author keystrokes; they let
the LLM reason locally without spending context window on
cross-references.
Empirically: if a feature is proposed and the LLM does not produce it
in unprompted code samples, the feature is proposed for the wrong
reason. The orchestrator's job is to notice that and cut.
## Decision 1: source = data, not text
A module is a JSON object with a fixed schema. There is no parser for
+83
View File
@@ -10782,3 +10782,86 @@ All three bench scripts re-run sequentially after edits:
- **Family 21+** — typeclasses, polymorphic ADTs at runtime,
pattern-binding generalisation. Orchestrator-level fork; needs
direct user input before dispatch.
## 2026-05-09 — Feature-acceptance criterion codified
Trigger: the typeclass-design conversation around 22a surfaced a
recurring meta-question — when is a proposed feature actually
worth shipping. The negative form was already in CLAUDE.md
("Design rationale ≠ implementation effort": cost is not a
reason for a feature). The positive form was implicit in many
decisions (Decision 10's reasoning explicitly invokes "what
LLMs are good at vs. not"; the JSON-over-text choice in
Decision 1 is justified by LLM-readability) but never stated as
a feature-acceptance gate.
This entry codifies it. New top-level section in DESIGN.md
("Feature-acceptance criterion"): a feature ships only if (1)
an LLM author naturally produces code that uses it without
prompting toward it, AND (2) the feature measurably improves
correctness or removes redundancy. Aesthetic appeal — "feels
elegant", "is idiomatic" — does not count; neither does human
ergonomics. Two corollaries: human-attractive but LLM-neutral
features (point-free style, operator overloading, implicit
conversions) are cut; human-hostile but LLM-friendly features
(JSON authoring surface, mandatory mode annotations, mandatory
top-level signatures) are kept.
Mirrored briefly in CLAUDE.md as a sub-section
"Feature acceptance: LLM utility", paired with the existing
"Design rationale ≠ implementation effort". The two together
fully narrow the space of valid feature rationales: not cost,
not aesthetics, only LLM-author utility.
### Why now
The typeclass conversation was the surfacing event. When asked
to construct two examples that pure monomorphisation cannot
handle (heterogeneous Show-able container; higher-rank
polymorphism), the natural response was: both are features that
an LLM author would not unprompted produce. Heterogeneous
containers reduce to closed-world sum types in practice;
higher-rank polymorphism reduces to two separate functions.
Without the rule explicitly named, the next instance of "should
we add feature X" would replay the same reasoning from scratch.
Codifying it now means future feature proposals get gated by an
articulated criterion, not by re-derivation.
### Implications for 22a (next iter)
The rule is the explicit basis for the typeclass-design choices
that 22a will make:
- **Monomorphisation as default dispatch strategy.** A pure-mono
language with rank-1-only polymorphism is exactly what a
natural LLM author produces. Dictionaries would handle features
(heterogeneous containers, higher-rank) that are real but not
LLM-natural — so they don't ship.
- **Higher-rank polymorphism rejected at parse time.** Error
message proposes the canonical workaround (two separate
functions). LLM-friendly: clear cut over subtle codegen
fallback.
- **Heterogeneous containers via sum types, not `dyn Show`.**
Same reasoning. Sum types are what the LLM would produce
unprompted; type-erased existentials are not.
If the rule were inverted — "ship every feature a sufficiently
sophisticated user might want" — 22a would commit to dictionary
passing and existential types from day one, and AILang would
gain the same dispatch overhead and codegen complexity that
make general-purpose languages opaque to the optimizer. The
rule cuts that off.
### Test state
288 / 0 / 3, unchanged. Documentation-only commit; no Rust,
schema, or bench changes.
### JOURNAL queue
Unchanged from 21'g. Next dispatch is 22a (typeclass design
iter), which is orchestrator-level work the orchestrator does
directly: DESIGN.md typeclass section, instantiation strategy,
schema nodes for `class` and `instance`, naming convention for
monomorphised functions. Implementer iter (22b) follows after
22a's design lands and is reviewed.