Skip to content

v35.6.0 — Compass §4.4 context-dimension closure (@safe sebagai default)

Choose a tag to compare

@fajarkraton fajarkraton released this 10 May 09:54
· 68 commits to main since this release

🛡️ Compass §4.4 fully closed — @safe sebagai default

The strategic compass §4.4 promise "@safe sebagai default" is now fully
realized at every dimension. v35.5.0 closed it at the type-system
dimension (affine D-FULL — non-primitive types are Move by default).
v35.6.0 closes it at the context dimension: fn without a context
annotation is now @safe (microkernel-isolated) by default, not the
permissive Function kind it used to default to.

Practically: an unannotated fn body is now microkernel-isolated —
hardware/OS builtins (port_outb, mem_alloc, irq_register,
fb_init …) trigger SE020 unless the fn opts in via @kernel /
@unsafe. Cross-context calls remain ergonomic: per the new D-α
decision, @safe MAY call @kernel and @device directly — it is
the canonical bridge layer matching the §5.4 worked example.

Headline change

// src/analyzer/type_check/check.rs:160
- _ => crate::analyzer::scope::ScopeKind::Function,  // permissive default
+ _ => crate::analyzer::scope::ScopeKind::Safe,       // microkernel-isolated default

Phase-by-phase shipped in this release

Phase Commit What
B0 + sub-B0 5d2d79da + a0a2083f Hands-on cascade probe — surfaced 4 root-cause buckets and the Compass-vs-code disagreement on @safe@kernel calls
D1 26bfdd8b Decision file: D-α (relax analyzer to match Compass) chosen over D-β (tighten Compass)
A.1 629af4c6 is_inside_function() extended to recognize Safe / Unsafe / Gpu scope kinds
A.2 ede47e5b + 487a8c79 D-α implementation: removed KernelCallInSafe / DeviceCallInSafe (SE021 / SE022) variants and 4 stale assertions
A.3 batch 1 ff1b629c 3 fb_* test sources annotated @kernel
A.3 batch 2 f91be569 15 eval_tests sources (4 pointer + 7 hal inline + 4 example .fj) annotated
A.3 batch 3 8a90a8ec Final 9 sites (Cap + tensor_workload + schedule_ai + p_all_features)
A.4 b5dab01a The flip itself + str_byte_at/str_len carve-out from safe_blocked_builtins
A.5 8e2838ef CHANGELOG + CLAUDE.md closure docs

Source carve-outs

str_byte_at and str_len are now allowed in @safe context.
Architecturally these are pure-functional byte-level string operations
(zero hardware access); inheriting them from os_builtins into
safe_blocked_builtins was a categorization error. The self-host
stdlib parser (stdlib/parser_ast.fj, 93 str_byte_at call sites)
needs them under the new default. Other os_builtins (mem_*, port_*,
irq_*, fb_*, kb_*, proc_*, …) remain safe_blocked_builtins
unchanged.

D-α: @safe is the ergonomic bridge

@safe no longer fires SE021 / SE022 on calls to @kernel / @device
functions. The CLAUDE.md §5.3 enforcement table — which always said
@safe → @kernel and @safe → @device are OK — now matches the
analyzer. The §5.4 worked bridge() -> Action example compiles
end-to-end.

Migration impact

For repository code: 28 sites annotated across 8 files (3 fb_* +
11 inline eval_tests + 4 example .fj + 9 final batch + follow-up).
Stdlib *.fj files required no annotation thanks to the str_byte_at
carve-out and the absence of other hw builtin usage in the chain
modules.

For external code: any unannotated user fn that calls hw/OS builtins
must now add @kernel / @unsafe. f-strings, struct ops, tensor ops,
and pure logic are all unaffected.

Engineering gates

Gate Result
cargo test --lib 7,633 / 7,633 PASS
cargo test --release --test selfhost_stage1_full 86 / 86 PASS @ ~18s
cargo test --release --test selfhost_phase17_self_compile 4 / 4 PASS @ ~110s — Stage 2 byte-equality preserved through D-α + A.1 + A.2 + A.3 + A.4
Full integ --no-fail-fast 0 failures across all 80 suites
cargo test --release --test context_safety_tests 149 / 149 PASS (+1 D-α bridge regression test)
cargo clippy --lib -- -D warnings clean
cargo fmt -- --check clean

Source of truth

Predecessors

v35.5.0 (FJARR_LEAK Phase 2 D-FULL — type-system §4.4 closure) →
v35.6.0 (context-dimension §4.4 closure — full §4.4 realized).

🤖 Generated with Claude Code