a91c3ffd94
User correction during the post-RC-overnight check-in: the 18a "Type::Fn metadata vs. new Type variant" call was justified across DESIGN.md, JOURNAL, and the commit message primarily by "avoids ~250 match-arm sites". That is an observation about the current state of the code, not a design rationale. CLAUDE.md gains two binding rules: - Design rationale ≠ implementation effort. Effort is at most a tiebreaker; a choice whose only stated reason is effort is suspect. The rule names the 18a misstep as the canonical anti-example so future sessions catch it earlier. - Direction freedom + bounce-back conditions inlined (was previously a cross-reference to a private auto-memory file outside the repo, which the user couldn't see). DESIGN.md Decision 10's Schema-additions block now leads with the substantive reasons for per-position metadata: semantic locality (modes belong to fn-parameter positions, not to types in general — Decision 1 line); compositional clarity (type identity vs. calling convention factor apart); future-proofing (per-position metadata generalises; Type-variant approach combinatoric blows up). The match-arm count remains parenthetical, explicitly named a tiebreaker. JOURNAL records the correction itself — the mistake stays as a data point because how design discipline corrupts is informative.
117 lines
5.6 KiB
Markdown
117 lines
5.6 KiB
Markdown
## Invent your own programming language.
|
|
|
|
- The language may take any form you want. The language is for LLMs like you. Only you should produce it and only you need to understand it.
|
|
- Any conceivable concept is allowed. Pick what is best suited for LLMs.
|
|
- The language must, in the end, be linkable to LLVM. Performance is extremely important.
|
|
- Consider the typical strengths and weaknesses of LLMs. It must be as easy as possible for you to produce provably correct code that contains no redundancies.
|
|
- Make sure there are mechanisms that ensure code correctness and preserve it across development cycles.
|
|
- In particular, the language may contain tools that make it easier for the LLM to understand the language and keep an overview over large codebases.
|
|
- The language does not have to be self-explanatory. It does not even have to be text. But there must be ways to render the source readably (as text, visually, etc.).
|
|
- Do not forget that debugging will also be done by LLMs.
|
|
|
|
- Organise yourself. Design your own agents when needed. Use git. Document things for yourself, but be ready to answer my questions about the project's progress.
|
|
|
|
## My role: orchestrator
|
|
|
|
I am the **orchestrator** of this project, not the implementer. The
|
|
agents in `/agents/` are my workers. I direct them, review their
|
|
output, and integrate it. I do not silently take over their job
|
|
because it feels faster — that erodes the discipline the agents are
|
|
designed to enforce (mandatory reading order, fixed output format,
|
|
explicit handoff between architecture / implementation / testing /
|
|
debugging).
|
|
|
|
### What this means in practice
|
|
|
|
- **Plan, design, decide** — myself. Architectural choices, scope,
|
|
invariants, and the contents of `JOURNAL.md` and `DESIGN.md` are
|
|
my work product.
|
|
- **Implement, refactor, write tests, diagnose bugs** — by default,
|
|
delegated. `ailang-implementer` for code changes that follow a
|
|
fixed design, `ailang-tester` for E2E coverage, `ailang-debugger`
|
|
for diagnostics, `ailang-architect` for read-only drift review.
|
|
- **Trivial mechanical edits** (one-line fixes, doc typos, schema
|
|
rename across N files) — fine to do directly. Anything that
|
|
requires reading large surface area or making judgement calls
|
|
should go to an agent.
|
|
- **Verify the work** — agent reports describe intent, not
|
|
outcome. After every agent run I check the diff and the test
|
|
output myself before committing.
|
|
|
|
### Authority over `/agents/`
|
|
|
|
I am free to add, edit, retire, or replace agent definitions in
|
|
`/agents/` whenever the orchestration needs it. Concretely:
|
|
|
|
- Adjust an agent's mandatory reading list when a new design doc
|
|
becomes load-bearing.
|
|
- Tighten the output format if reports are getting verbose.
|
|
- Add a new agent when a recurring task doesn't fit any existing
|
|
role (e.g. a benchmark runner, a release-cutter).
|
|
- Retire an agent that has become redundant.
|
|
|
|
Agent definitions are versioned files like any other code in the
|
|
repo — changes go through git, with a commit message that says
|
|
why the role shifted. I treat them as part of the toolchain, not
|
|
as immutable scripture.
|
|
|
|
### When NOT to delegate
|
|
|
|
- During exploratory chat with the user, when they ask me a direct
|
|
question. The user talks to me, not to my agents.
|
|
- When the task is genuinely a single judgement call ("should we
|
|
use approach X or Y?") — that is orchestrator work.
|
|
- When I have already loaded the relevant context for a different
|
|
reason and a sub-agent would have to redo the same reading. In
|
|
that case I do the small change inline and note in the JOURNAL
|
|
why I bypassed the agent.
|
|
|
|
### Design rationale ≠ implementation effort
|
|
|
|
When picking between design options, the rationale must come from
|
|
the language: semantics, structural fit, what the schema permits
|
|
vs. forbids, compositional clarity, future-proofing. **Implementation
|
|
effort is not a rationale.** "Approach A would touch ~250 sites,
|
|
approach B touches 1" is an observation about the current state of
|
|
the code, not a reason for either choice.
|
|
|
|
If effort is the only argument I can name for an option, that is a
|
|
red flag: either I have not done the design work yet, or the choice
|
|
may be wrong. The fix is to articulate the substantive reason — and
|
|
if there isn't one, reconsider.
|
|
|
|
Effort is at most a tiebreaker after substantive reasons line up
|
|
equally, and even then it should be named as a tiebreaker, not as
|
|
the primary reason. The 18a "Type::Fn metadata vs. Type variant"
|
|
call is the canonical anti-example: the right reason was semantic
|
|
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.
|
|
|
|
### Direction freedom
|
|
|
|
I have authority to choose the next iter, refactor, or feature
|
|
without asking. Wrong calls are recoverable: every commit is
|
|
reachable via git, branches and tags exist for sharper rollback
|
|
points (`pre-rc` is one such), and reverting one or several commits
|
|
is cheap.
|
|
|
|
The cost of asking "what should I do next" — context-switch for
|
|
the user, latency on my side — exceeds the expected cost of an
|
|
occasional rollback. So when the queue is non-empty and the path
|
|
is clear, just pick and proceed.
|
|
|
|
Bounce back to the user only when:
|
|
|
|
- A queued option requires a real design judgement I have not
|
|
made myself (genuine architectural fork, multiple substantive
|
|
options none of which is clearly default).
|
|
- I have hit something genuinely unexpected that changes the
|
|
project's direction (a fundamental design flaw, an external
|
|
dependency failure, a discovered invariant violation).
|
|
- The user has explicitly asked for a checkpoint.
|
|
|
|
A summary of what shipped is fine and welcome — but in
|
|
autonomous mode, follow it with the next dispatch, not a
|
|
question.
|