Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
cba4d96
Initialize gems/ruby-to-clear transpiler and write design doc and int…
cuzzo Jun 25, 2026
cb8dc02
Support translating Ruby each to native Clear pipeline EACH
cuzzo Jun 25, 2026
f39a761
Support self, local variable targets, block argument mapping, and tra…
cuzzo Jun 25, 2026
08e386c
Enforce strict transpilation correctness and block scoping
cuzzo Jun 25, 2026
dd93c04
Add compound assignment and optional parameter support
cuzzo Jun 25, 2026
3ff0f28
Fix parameter parsing fallback bug in fact-mine for parameterless Rub…
cuzzo Jun 25, 2026
b94c84b
Auto-apply verified Sorbet type annotations and struct RBI signatures
cuzzo Jun 25, 2026
5cb17d7
Fix circular load-order dependency on BgTransformValue in FsmTransfor…
cuzzo Jun 25, 2026
7a09090
Classify collection types containing T.untyped as untyped in soundnes…
cuzzo Jun 25, 2026
f51f633
Ignore gems/ruby-to-clear in Sorbet typecheck
cuzzo Jun 25, 2026
486ea89
Resolve pre-existing Sorbet static type errors
cuzzo Jun 25, 2026
eb7ed2e
Instrument T::Struct properties and mutations in nil-kill runtime tracer
cuzzo Jun 25, 2026
40235e4
Keep only T::Struct#initialize hook to avoid Sorbet sig validation issue
cuzzo Jun 25, 2026
5123337
auto-type: fix find_sig_idx to stop searching upward when encounterin…
cuzzo Jun 26, 2026
1fe5cc6
ast: add missing String return type sigs for name methods
cuzzo Jun 26, 2026
1792396
Resolve struct fields RBI validation errors and regenerate RBI
cuzzo Jun 26, 2026
4170d5b
Optimize AST struct fields type annotations in sorbet/rbi/ast-struct-…
cuzzo Jun 26, 2026
8c95b90
Fix nil-kill RBI profiling and unqualified struct namespace extraction
cuzzo Jun 27, 2026
ea07a00
Fix relative vs absolute path mismatch in resolve_struct_declaration_…
cuzzo Jun 27, 2026
b5873b4
Implement AST and MIR node class collapsing in sorbet_type and static…
cuzzo Jun 27, 2026
81c9f4e
Optimize legacy trace loading in Normalizer and capture post-initiali…
cuzzo Jun 27, 2026
56ce0d6
Apply 148 verified struct field type signatures via auto-type loop
cuzzo Jun 27, 2026
6ec3276
Apply 78 verified parameter and return type corrections in src/
cuzzo Jun 27, 2026
15727a2
Create Z3 SMT global subtyping solver design document
cuzzo Jun 28, 2026
35725ad
Implement Z3 SMT subtyping lattice generator (Phase 1)
cuzzo Jun 28, 2026
0181b55
Implement Z3 SMT static data-flow constraint solving (Phase 2)
cuzzo Jun 28, 2026
55aefb5
Implement Z3 SMT specificity maximization and topological sort (Phase 3)
cuzzo Jun 28, 2026
64e6f5c
Optimize SMT Z3 type solving pipeline with parallel consistency clean…
cuzzo Jun 28, 2026
0451112
Allow RBI and struct actions to bypass Z3 global consistency filter
cuzzo Jun 29, 2026
b8e22f6
Apply verified AST and MIR base-class collection signatures
cuzzo Jun 29, 2026
f36eb05
Epic 1: NilKill Infer Oracle Harness
cuzzo Jun 29, 2026
36ec7ef
Epic 2: Rust Foundation & Schemas
cuzzo Jun 29, 2026
489d15f
Migrate nil-kill infer orchestration to Rust
cuzzo Jun 29, 2026
c778930
Expand rust inference unit tests to reach >90% coverage
cuzzo Jun 29, 2026
fc192d3
test: Increase nil-kill test coverage above 95%
cuzzo Jun 29, 2026
04b04d8
fix: unconditionally run CLI in nil-kill executable
cuzzo Jun 30, 2026
724a9c1
Fix Derived-State Staleness false positives in Rust by stripping type…
cuzzo Jun 30, 2026
7b0df4f
Filter out structural pattern match 'let' bindings from NeglectedPath…
cuzzo Jun 30, 2026
e7c8c64
Perf: Skip JSON serialization of ASTs for decomplex reports
cuzzo Jun 30, 2026
e86fb0d
Perf: Optimize co_update and decision_pressure detectors string handling
cuzzo Jun 30, 2026
84ea7c0
Docs: Add architecture proposal for empirical Big-O analysis
cuzzo Jun 30, 2026
7768f75
Docs: Add architecture proposal for static Big-O analysis in Espalier
cuzzo Jun 30, 2026
f077121
Add ruby-to-clear improvement roadmap and audit CLI
cuzzo Jun 29, 2026
734a3db
Preserve partial output for unsupported Ruby nodes
cuzzo Jun 29, 2026
e382853
Add roadmap metrics to ruby-to-clear audit
cuzzo Jun 29, 2026
7e74f58
Make ruby-to-clear method registry receiver-aware
cuzzo Jun 29, 2026
f0b45d1
Add safe enumerable block translations
cuzzo Jun 29, 2026
0af8de3
Add thin stdlib adapters to ruby-to-clear
cuzzo Jun 29, 2026
01fc055
Use Sorbet metadata in ruby-to-clear output
cuzzo Jun 29, 2026
1aff7e9
Classify dynamic Ruby blockers in ruby-to-clear
cuzzo Jun 29, 2026
71bb4f7
Add ruby-to-clear oracle coverage gate
cuzzo Jun 29, 2026
f0ecfc5
Document ruby-to-clear 95 percent roadmap
cuzzo Jun 29, 2026
e80210e
Clarify ruby-to-clear language design guardrails
cuzzo Jun 29, 2026
3e2127a
Add keyword args and block lowering design
cuzzo Jun 29, 2026
9e4d11b
Stack rank ruby-to-clear coverage tasks
cuzzo Jun 29, 2026
52c23c6
Fix ruby-to-clear interpolated string traversal
cuzzo Jun 29, 2026
82d288d
Preserve Ruby module bodies in ruby-to-clear
cuzzo Jun 29, 2026
d62b5e9
Support static keyword parameters in ruby-to-clear
cuzzo Jun 29, 2026
8ab722e
Translate safe keyword constructors in ruby-to-clear
cuzzo Jun 29, 2026
6136915
Support multi-statement pipeline block values
cuzzo Jun 29, 2026
b7a460d
Add CLEAR stdlib public spec
cuzzo Jun 29, 2026
77e164f
Add stdlib design principles
cuzzo Jun 29, 2026
105f824
Generate split stdlib docs from code
cuzzo Jun 29, 2026
6596b7c
Add prototype fs stdlib package
cuzzo Jun 29, 2026
da8d852
Support source value blocks in pipelines
cuzzo Jun 29, 2026
0bcb380
Map Ruby file IO to CLEAR fs package
cuzzo Jun 29, 2026
ec77c15
Cover value block parser branches
cuzzo Jun 29, 2026
2231eac
Satisfy Sorbet for value blocks
cuzzo Jun 29, 2026
a015f71
Add value block integration coverage
cuzzo Jun 29, 2026
5b28037
Update generated metadata
cuzzo Jun 29, 2026
9610efa
Document post value block ruby-to-clear work
cuzzo Jun 29, 2026
fd924f1
Add shared ruby block lowering result
cuzzo Jun 29, 2026
9f9f852
Expand ruby enumerable pipeline lowering
cuzzo Jun 29, 2026
99fadaa
Normalize ruby fs and path mappings
cuzzo Jun 29, 2026
f50c871
Track receiver shapes for ruby calls
cuzzo Jun 29, 2026
156cccb
Report unlocked ruby transpiler audit buckets
cuzzo Jun 29, 2026
75c8aab
Cover and fix ruby block-local lowering
cuzzo Jun 29, 2026
02b8196
Lower ruby floats and Sorbet bind rescue nil
cuzzo Jun 29, 2026
6eb9793
Update ruby-to-clear spec example metadata
cuzzo Jun 29, 2026
e2de8d6
Add CLEAR destructuring assignment support
cuzzo Jun 30, 2026
f296959
Lower fixed Ruby multi-write to CLEAR destructuring
cuzzo Jun 30, 2026
d66f82d
Refine destructuring lowering helpers
cuzzo Jun 30, 2026
9988c11
Extract destructuring annotator domain
cuzzo Jun 30, 2026
344c6e6
Replace dynamic ivar metadata access
cuzzo Jun 30, 2026
bdda80f
Tighten diagnostic source protocol
cuzzo Jun 30, 2026
165f649
Fix nil-kill Rust infer handoff
cuzzo Jun 30, 2026
0588368
Improve nil-kill field inference and auto-type rewrites
cuzzo Jun 30, 2026
8fec34f
Improve nil-kill auto-type coverage
cuzzo Jun 30, 2026
d0ad262
ci: build nil-kill Rust infer binary
cuzzo Jun 30, 2026
c32ac56
test: update decomplex report facts calls
cuzzo Jun 30, 2026
54d6678
fix: discard value-block prefix expressions
cuzzo Jun 30, 2026
2a827d7
ci: refresh clear attr RBI
cuzzo Jun 30, 2026
a65647b
fix: preserve move statements during discard lowering
cuzzo Jun 30, 2026
578b1e4
ci: cap decomplex SARIF upload size
cuzzo Jun 30, 2026
64fc9a6
ci: refresh mutant patch contexts
cuzzo Jun 30, 2026
1bc7e50
ci: refresh ruby mutant baselines
cuzzo Jul 1, 2026
1058c4b
ci: refresh remaining ruby mutant gates
cuzzo Jul 1, 2026
6aa5c7c
Merge pull request #141 from cuzzo/rb-to-clear-improv
cuzzo Jul 1, 2026
2dba474
ci: force-refresh PR base refs
cuzzo Jul 1, 2026
705a85c
test: clean up nil-kill oracle fixtures
cuzzo Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,14 @@ jobs:
- name: Install Tree-sitter grammars
run: npm install --legacy-peer-deps
- uses: dtolnay/rust-toolchain@stable
- name: Build fact-mine-rust binary
run: cargo build --release --manifest-path gems/fact-mine/Cargo.toml
- name: Build Rust binaries
run: |
cargo build --release --manifest-path gems/fact-mine/Cargo.toml
cargo build --release --manifest-path gems/nil-kill/Cargo.toml
- run: bundle exec rspec gems/nil-kill/spec
env:
FACT_MINE_RUST_BINARY: ./gems/fact-mine/target/release/fact-mine-rust
NIL_KILL_INFER_RUST_BINARY: ./gems/nil-kill/target/release/nil-kill-infer-rust

boobytrap-go-unit:
name: boobytrap Go tests
Expand Down Expand Up @@ -185,11 +188,13 @@ jobs:
- name: Build Rust binaries
run: |
cargo build --release --manifest-path gems/fact-mine/Cargo.toml
cargo build --release --manifest-path gems/nil-kill/Cargo.toml
cargo build --release --manifest-path gems/decomplex/Cargo.toml
- name: Run Ruby gem tests with SimpleCov
run: bundle exec ruby tools/run_ruby_gem_coverage.rb
env:
FACT_MINE_RUST_BINARY: ./gems/fact-mine/target/release/fact-mine-rust
NIL_KILL_INFER_RUST_BINARY: ./gems/nil-kill/target/release/nil-kill-infer-rust
- uses: actions/upload-artifact@v4
with:
name: ruby-coverage-gems
Expand Down Expand Up @@ -461,7 +466,7 @@ jobs:
version: ${{ env.ZIG_VERSION }}
- name: Generate lint SARIF
run: |
git fetch origin "${{ github.event.pull_request.base.ref }}:refs/remotes/origin/${{ github.event.pull_request.base.ref }}" --depth=1
git fetch origin "+${{ github.event.pull_request.base.ref }}:refs/remotes/origin/${{ github.event.pull_request.base.ref }}" --depth=1
bundle exec ruby tools/generate_lint_sarif.rb \
--repo=. \
--base="origin/${{ github.event.pull_request.base.ref }}" \
Expand Down Expand Up @@ -1395,7 +1400,7 @@ jobs:
path: tmp/zig-special-coverage-artifacts
- name: Generate SlopCop constraint SARIF
run: |
git fetch origin "${{ github.event.pull_request.base.ref }}:refs/remotes/origin/${{ github.event.pull_request.base.ref }}" --depth=1
git fetch origin "+${{ github.event.pull_request.base.ref }}:refs/remotes/origin/${{ github.event.pull_request.base.ref }}" --depth=1
mkdir -p tmp
args=()
while IFS= read -r path; do
Expand Down Expand Up @@ -1491,7 +1496,7 @@ jobs:
env:
FACT_MINE_RUST_BINARY: ./gems/fact-mine/target/release/fact-mine-rust
run: |
git fetch origin "${{ github.event.pull_request.base.ref }}:refs/remotes/origin/${{ github.event.pull_request.base.ref }}" --depth=1
git fetch origin "+${{ github.event.pull_request.base.ref }}:refs/remotes/origin/${{ github.event.pull_request.base.ref }}" --depth=1
mkdir -p tmp/generalized-gems-coverage tmp/generalized-gems-sarif
coverage_args=()
while IFS= read -r path; do
Expand Down Expand Up @@ -1601,7 +1606,7 @@ jobs:
path: tmp/zig-coverage-artifacts
- name: Generate diff coverage bucket markdown
run: |
git fetch origin "${{ github.event.pull_request.base.ref }}:refs/remotes/origin/${{ github.event.pull_request.base.ref }}" --depth=1
git fetch origin "+${{ github.event.pull_request.base.ref }}:refs/remotes/origin/${{ github.event.pull_request.base.ref }}" --depth=1
mkdir -p tmp
ruby_paths="$(find tmp/ruby-coverage-artifacts -name .resultset.json -type f | sort | paste -sd: -)"
zig_paths="$(find tmp/zig-coverage-artifacts -name cobertura.xml -type f | sort | paste -sd: -)"
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,12 @@ transpile-tests/fuzz/*.cht
**/.zig-cache/
**/zig-out/
**/*.clear-build.json
**/__pycache__/

# Generated architecture reports
gems/espalier/architecture.yml

# Decomplex native Rust build artifacts
gems/decomplex/target/
gems/fact-mine/target/
gems/nil-kill/target/
4 changes: 2 additions & 2 deletions docs/agents/self-host-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ Refactor by blocker category, not by file.

## Prism Audit Findings

The first migration audit script lives at `tools/ruby-to-clear.rb` and is run as:
The first migration audit command lives in the `ruby-to-clear` gem and is run as:

```text
ruby tools/ruby-to-clear.rb --top 30
ruby gems/ruby-to-clear/exe/ruby-to-clear-audit --top 30
```

Current `src/**/*.rb` results:
Expand Down
269 changes: 269 additions & 0 deletions docs/agents/stdlib-design-principles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
# CLEAR Stdlib Design Principles

Status: design principles.

Date: 2026-06-29.

## Core Goal

The stdlib's first architectural goal is composability with CLEAR's effects,
capabilities, and tense system.

Stdlib APIs should compose across:

- pure/stateless functions;
- stateful handles such as files, sockets, scanners, builders, and streams;
- capability-wrapped values such as `@locked`, `@shared`, `@local`, and
future package permissions;
- effectful boundaries such as file IO, network IO, process execution, time,
randomness, allocation, and blocking;
- tense-aware values, including snapshots, live state, historical values,
derived state, and streamed/current values where the language supports them.

The user should be able to start with a high-level stateless API and only add
state, effects, capabilities, or tense-specific machinery when the program
actually needs it.

## User-Facing Priority

After composability, the stdlib's highest user-facing priority is to feel as
high-level as possible.

This is true even when a traditional systems language would consider the API
"too convenient" or "not explicit enough." CLEAR is not trying to make every
program read like Zig, C, or Rust. CLEAR should give users Ruby/Elixir-level
ergonomics by default and expose systems-level detail only when that detail is
needed for correctness, performance, or capability control.

The default bias is:

- Prefer a high-level interface when the lower-level interface mainly exposes
implementation mechanics.
- Prefer Ruby/Elixir-style convenience when the operation has an obvious safe
default.
- Prefer explicit systems controls only when hiding them would create a major
correctness, performance, or security flaw.
- When a harder API is necessary, make it only slightly harder than the
high-level path and explain what additional control the user is getting.

This means the stdlib should not force users to think about allocators, readers,
writers, buffers, file descriptors, backpressure, stream lifetimes, socket
polling, or scheduler integration for common code. Those concepts should exist,
but they should be opt-in.

## What Counts As A Major Systems Flaw

We should deviate from a high-level API only for major flaws, not for ordinary
systems-language taste.

Major flaws include:

- hidden unbounded memory growth in common usage;
- impossible or misleading resource lifetime semantics;
- data races or capability violations;
- effect/capability behavior that the compiler cannot track;
- performance cliffs that are large, common, and hard to diagnose;
- APIs that make deterministic compiler output unreliable;
- APIs that prevent a lower-level zero-cost path from existing.

Non-major reasons are not enough by themselves:

- "Zig would make the allocator explicit."
- "Java would force a stream object."
- "Rust would encode this as a trait-heavy iterator stack."
- "C would expose the buffer and length."

Those can be valid implementation details. They are not automatically good
CLEAR user interfaces.

## IO And Streams Are The Test Case

File and network IO are the clearest examples.

CLEAR should not make opening files or doing file/network IO as hard as Java or
Zig for ordinary users. A user should be able to write obvious high-level code:

```ruby clear illustrative
text = fs.read("config.clear") OR RAISE;
lines = fs.readLines("users.txt") OR RAISE;
fs.write("out.txt", report) OR RAISE;
```

The same principle applies to pipelines. The pipeline system should default to
using streams internally where it can, because streaming is the right execution
strategy for IO and large inputs. The final result should be driven by an
explicit terminal or destination type.

Illustrative shape:

```ruby clear illustrative
users: User[] = (fs.readLines("users.csv") OR RAISE)
|> MAP { parseUser(_) }
|> SELECT { _.active?() };
```

The implementation should be free to stream `users.csv` line by line. The user
should not need to opt into streaming just to avoid a bad implementation. But
because the assignment target is a list, the final value should collect into a
list.

If the user wants a stream, hashmap, set, or another collection, they should ask
for it explicitly:

```ruby clear illustrative
active_stream = (fs.readLines("users.csv") OR RAISE)
|> MAP { parseUser(_) }
|> SELECT { _.active?() }
|> AS_STREAM;

users_by_id = (fs.readLines("users.csv") OR RAISE)
|> MAP { parseUser(_) }
|> COLLECT_MAP { _.id => _ };

unique_domains = (fs.readLines("emails.txt") OR RAISE)
|> MAP { domainOf(_) }
|> COLLECT_SET;
```

The exact names are not settled. The principle is settled:

- streams are a preferred internal execution strategy;
- result shape comes from an explicit terminal or destination type;
- directory scans, globbing, and collection do not insert hidden sorts;
- systems programmers can request stream/control forms without fighting the
high-level API.

Ordering is explicit:

```ruby clear illustrative
files = fs.glob("src/**/*.cht") OR RAISE;
sorted = files |> ORDER_BY _;
```

`ORDER_BY` is the current explicit sort-by-key operator. A future `SORT`
shorthand for sorting by the singular value depends on the traits/interfaces
or duck-typed ordering decision.

This is the kind of tradeoff CLEAR should make repeatedly. A systems language
might require explicit stream types everywhere. CLEAR should infer and use the
efficient strategy internally, then return the ergonomic shape by default.

## Stateless And Stateful Pairs

Many stdlib areas need both stateless and stateful APIs.

The stateless form should be the default:

```ruby
content = fs.read("input.txt");
tokens = scanner.scanAll(source);
json = Json.parse(text);
```

The stateful form should appear when it buys something real:

```ruby
file = fs.open("input.txt");
stream = file.lines();
scan = Scanner.new(source);
builder = StringBuilder.new();
```

The stateful form should not be the only way to do common work. It exists for
large inputs, incremental processing, resource reuse, backpressure, explicit
cleanup, and performance-sensitive code.

## Effects And Capabilities Should Be Visible, Not Noisy

The compiler should know that `fs.read` has a file-read effect, allocates, and
can fail. The user should not have to spell all of that at every call site.

Preferred posture:

- Effects are inferred for normal code.
- Public package boundaries document effects.
- Strict modes can require effect declarations.
- Capability permissions are visible where they matter, especially package and
host boundaries.
- High-level APIs remain high-level unless the user opts into strict control.

For example, `fs.read("config.clear")` should be easy. In a restricted package
or strict build, the compiler can still require that the package is allowed to
perform file reads.

## Naming Bias

Prefer names that read naturally in pipelines and UFCS:

- Ruby/Elixir-style collection names: `map`, `select`, `reject`, `filterMap`,
`flatMap`, `find`, `any?`, `all?`, `reduce`; pipeline ordering uses
`ORDER_BY`.
- Ruby-style predicates when they are compact and obvious: `empty?`,
`present?`, `nil?`, `startsWith?`, `endsWith?`.
- Systems names only at systems boundaries: `open`, `close`, `flush`, `sync`,
`readInto`, `writeAll`, `reserve`, `capacity`.

Avoid names that force users to learn the backing implementation before they
can write ordinary code.

## Defaults

Default choices should be optimized for high-level users:

| Area | Default | Explicit lower-level path |
| --- | --- | --- |
| Pipeline result | destination type or explicit terminal | `AS_STREAM`, `COLLECT_LIST`, `COLLECT_MAP`, `COLLECT_SET`, fixed array |
| File read | read whole text or lines | open handle, stream lines, read bytes, read into buffer |
| Network read | message/bytes helper where possible | socket/client resource and stream control |
| Strings | UTF-8 text operations | byte buffers and byte indexing |
| Errors | `!T` fallibility with `OR` propagation | named error taxonomy and explicit result handling |
| Effects | inferred and documented | strict declarations and package permissions |
| Allocation | implicit safe allocation | reserve/capacity/allocator-aware APIs |
| Mutation | immutable/new collection transforms | explicit mutating names |

The lower-level path must exist. It should not be the first thing users see.

## Key Decisions Before Self-Host Implementation

The self-host project can implement a lot with existing intrinsics and thin
source packages, but these decisions should be made before most stdlib work
lands:

1. **Pipeline result defaults.** Pipelines use streams internally where
practical and collect according to explicit terminal or destination type.
2. **Explicit collection request syntax.** Choose names and syntax for
`AS_STREAM`, `COLLECT_LIST`, `COLLECT_MAP`, `COLLECT_SET`, and typed
collection targets.
3. **Error model.** Prototype stdlib APIs expose native `!T` fallibility and
`OR` propagation. The remaining decision is the named error taxonomy and
future relationship to `Result`.
4. **Effect visibility.** Decide which effects are public stdlib contracts for
self-host packages: file read/write, process/env, network read/write, time,
random, allocation, blocking, and extern.
5. **Capability permissions.** Decide how packages declare or receive authority
to touch files, network, processes, environment, clocks, and randomness.
6. **Resource lifetime model.** Decide how high-level APIs auto-close resources
and how stateful handles express cleanup, ownership, borrowing, and escape.
7. **Stream lifetime and backpressure.** Decide how streams interact with file
handles, sockets, fibers, scheduler suspension, and collection boundaries.
8. **Tense integration.** Decide how stdlib APIs expose snapshots, live views,
historical values, and streamed current values without making ordinary APIs
noisy.
9. **Stateless/stateful API pairing.** Decide the naming convention for simple
convenience functions versus explicit handle/builder/scanner/stream APIs.
10. **String and bytes split.** Decide byte indexing, codepoint indexing,
invalid UTF-8 handling, and conversions between `String` and byte buffers.
11. **Ordering.** Directory listing and globbing should be unsorted streams by
default. Decide the explicit ordered variants and future `SORT`/ordering
interface for maps, sets, JSON object generation, and diagnostics.
12. **Generic and iterator model.** Decide how collection functions specialize
without importing a class/trait/interface model that CLEAR does not want.
13. **Mutation convention.** Decide how mutating collection/string operations
are named and how aliasing/capability hazards are rejected.
14. **Docs stability labels.** Decide the public status vocabulary for planned,
prototype, self-host required, intrinsic today, and stable APIs so docs do
not imply premature compatibility.

These decisions should not block every tiny wrapper, but they should block wide
stdlib implementation. We can publish the shape in docs first, then implement
only the self-host subset once the defaults are coherent.
Loading
Loading