diff --git a/CLAUDE.md b/CLAUDE.md index fa620ff..3559068 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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 diff --git a/docs/DESIGN.md b/docs/DESIGN.md index bd86d33..95465c1 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -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 diff --git a/docs/JOURNAL.md b/docs/JOURNAL.md index df1e513..9de1172 100644 --- a/docs/JOURNAL.md +++ b/docs/JOURNAL.md @@ -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.