All 176 files in the four accumulating directories now use a zero-padded 4-digit counter prefix that reflects creation order (`NNNN-slug.md`). The counter is assigned per directory in strict git-log creation order; ties broken alphabetically by original name. The old `YYYY-MM-DD-` prefix on docs/specs/ and docs/plans/ files is dropped — the date is recoverable from git log and the counter carries the ordering. A file's counter is stable for the life of the file: never reassigned, never reused, never compacted. Deleted files retire their counter; subsequent files do not fill the gap. This is the property that lets cross-references stay literal — refs use the full filename including the counter (`design/contracts/0007-honesty-rule.md`) so they grep cleanly and resolve directly without a glob step. 313 cross-references updated across .md/.rs/.toml/.c/.json files (test pins, include_str! paths, design-INDEX entries, baseline notes, runtime C comments, inter-contract markdown links incl. bare basename and `../models/foo.md` forms). CLAUDE.md gets a new "File-naming convention" section spelling out the rule and rationale. skills/brainstorm/SKILL.md and skills/planner/SKILL.md updated so new spec/plan creation produces counter-prefixed names from the start. The full test suite (cargo test --workspace) passes.
1.9 KiB
Language-design constraints (binding)
Language-design constraints (binding)
The four constraints below are necessary preconditions for RC to be sound and complete without a cycle-collector backstop. They are not new — AILang already satisfies all four — but the memory model makes them load-bearing rather than incidental:
- Strict evaluation. Every
Term::App(see Data model) argument is fully evaluated before the call. No laziness, no thunks. (Already true.) - No recursive value bindings.
(let x EXPR ...)evaluatesEXPRin a scope wherexis not bound. Recursion is exclusively viaTerm::LetRec(which binds a fn, not a value) and module-level fn defs. (Already true.) - No shared mutable refs. Values are immutable once
constructed. There is no
ref,IORef,Mutex, or any primitive that allows a value to be mutated from a position outside its allocation. (Already true.) - ADTs are acyclic by construction. Strict evaluation + no-recursive-value-bindings + no-shared-mutable-refs together guarantee that any value graph reachable from a binding is a DAG. The reference graph has no cycles. (Follows from 1–3.)
Laziness, recursive value bindings, shared mutable state, or any feature that creates cycles is rejected at design time unless the proposal proves the cycle is collectible by an extension (e.g. linear ownership).
These constraints are the precondition for the memory model: a sound RC implementation without a cycle-collector backstop requires the reference graph to be a DAG, which constraint 4 establishes from 1–3. They are also the load-bearing structural reason behind several rejections under the feature-acceptance bug-class-reintroduction discriminator (notably iterated-mutable-state reasoning).
Ratified by: crates/ailang-check/src/uniqueness.rs (in-source mod tests).