Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
79 changes: 79 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,85 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

## [0.33.0] - 2026-06-17

Depth-2 nested-string transcoding release: closes the last gap of the #272
async cross-encoding campaign by implementing `list<list<string>>`
cross-encoding transcoding (#286), corrects an understated traceability claim
(#289), and fixes the recurring fuzz-CI runner-drift flake (#168). 5 PRs since
v0.32.0; each Tier-5 change adversarially Mythos-gated (REFUTED), no admin merge.

### Added

- **#286 — depth-2 `list<list<string>>` async cross-encoding transcoding**
(#290 5d-pre, #291 RESULT, #292 PARAM). The async-lift nested-indirection
patchers now recurse one level at codegen time: a `list<list<string>>` param
or result is deep-copied/relocated and its *deepest* strings transcoded
across the encoding boundary, in all 6 directions × {callback, stackful},
instead of failing loud. Implemented as a type-carrying `Indirection`
descriptor (5d-pre, behaviour-preserving) + per-depth disjoint local blocks
with a shared transcode-scratch (only the deepest leaf transcodes, so the
feared `l_new_ptr` collision is avoided structurally). Each increment was
verified by a runtime-differential oracle (following the doubly relocated
pointers) + a REAL-adapter `wasmparser::Validator` budget test, and an
adversarial Mythos delta-pass (REFUTED across directions, aliasing, and
empty-inner-list edges). This **closes #286** and completes the #272 campaign
(all 6 directions × {flat, one-level, depth-2} × {params, results}).

### Fixed

- **#168 — fuzz-CI runner cargo-config drift.** The Fuzz-smoke jobs failed
intermittently per-runner with `ToolNotFound: x86_64-linux-musl-g++`. Root
cause: cargo-fuzz *derives* its target from a drifted runner's
`[build] target = musl` cargo config and passes it as an explicit `--target`,
which beats the `CARGO_BUILD_TARGET` env override (cargo precedence). Fixed by
pinning `cargo fuzz run --target x86_64-unknown-linux-gnu` (highest-precedence
slot), forcing the host gnu target on every runner. The infra root-cause
(re-image the rust-cpu runners) remains tracked on #168 (smithy's domain).

### Changed (traceability)

- **SR-41** description + verification updated: coverage now explicitly includes
two-level list nesting (`list<list<string>>`, #286); the residual fail-loud
boundary moved to deeper-than-two-level nesting. Cites the new `d5d_*` depth-2
runtime + real-adapter budget oracles.
- **LS-F-27** de-staled: the async fail-loud guard's residual set narrowed from
`list<list<string>>` (now transcoded) to `list<list<list<string>>>` (depth-3+).
- **SR-17** (#289): corrected an *understated* gap — the UTF-16→UTF-8 reverse
direction and lone-surrogate U+FFFD substitution were already covered by
passing runtime oracles (closed during #272), but the SR text still listed
them as a carried gap. Now cites the closing oracles. (Understated, not
overstated — the safe direction, but still a traceability defect.)

### Falsification

This release's central claim — depth-2 `list<list<string>>` cross-encoding
transcodes correctly and only depth-2 is allowed — would be falsified by: a
fused depth-2 nested-string param/result whose deepest string reads back under
the wrong encoding or via a pointer still aimed into the source memory; a
generated callback/stackful adapter referencing an out-of-budget or wrong local
(rejected by `wasmparser::Validator`); or a `list<list<u8>>` / depth-3 site that
is *allowed* (transcoded/raw-copied) rather than failing loud. The `d5d_*`
oracles + guard boundary tests exercise each; all pass, none falsify.

### Known gaps (disclosed)

- **Depth-3+ list nesting** (`list<list<list<string>>>`) fails loud (LS-F-27),
not transcoded — bounded by the emitter's one-level recursion + the
async-adapter local budget. Extends to depth-N straightforwardly if needed.
- **Async-lift e2e** remains fuse-only/structural in this repo's tests; the full
trampoline run is kiln-gated (out of scope here). The REAL-adapter budget
validator tests are the compensating control.
- **Kani proofs not in CI** (runners lack the toolchain); run locally. The #286
equivalence proofs are additionally intractable under CBMC (allocation-heavy
recursive `cabi_size_align`) — the differential runtime oracle is the
load-bearing check there.
- **#168 fuzz fix** is a meld-side mitigation verified by contract + ongoing CI
observation (the drifted runner is not locally reproducible); the infra
re-imaging root-cause stays open.
- 16 baseline SRs remain `implemented` (not yet `verified`) — unchanged from
v0.32.0; not regressed by this release.

## [0.32.0] - 2026-06-15

String-transcoding correctness release: completes spec-faithful
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ exclude = [
]

[workspace.package]
version = "0.32.0"
version = "0.33.0"
authors = ["PulseEngine <https://github.com/pulseengine>"]
edition = "2024"
license = "Apache-2.0"
Expand Down
46 changes: 30 additions & 16 deletions safety/requirements/safety-requirements.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1230,14 +1230,17 @@ artifacts:
that cross a string-encoding boundary, rather than raw-copying them
under the wrong encoding. Coverage: all six ordered encoding-pair
directions over utf8 / utf16 / latin1+utf16 (CompactUTF16, the
UTF16_TAG = 1<<31 tagged-length form), at the top level and one level
of list / record / tuple nesting, in both the callback and stackful
async variants. A nested `list<u8>` shall be deep-copied verbatim,
never transcoded (string-vs-byte-list disambiguation via the WIT type).
Any not-yet-supported shape — deeper-than-one-level list nesting
(`list<list<string>>`, #286) — shall fail loud (the LS-F-27 guard),
never silently mis-transcode. Extends SR-17 (sync transcoding) to the
async-lift adapter path.
UTF16_TAG = 1<<31 tagged-length form), at the top level, one level of
list / record / tuple nesting, AND two levels of list nesting
(`list<list<string>>`, #286 — both params and results, via codegen-time
recursion in emit_{patch,param}_nested_indirections), in both the
callback and stackful async variants. A nested `list<u8>` shall be
deep-copied verbatim, never transcoded (string-vs-byte-list
disambiguation via the WIT type). Any deeper-than-two-level list nesting
(`list<list<list<string>>>`) shall fail loud (the LS-F-27 guard), never
silently mis-transcode — the allow-set is bounded to the depth the
emitter recurses (one level) and the async-adapter local budget supports.
Extends SR-17 (sync transcoding) to the async-lift adapter path.
status: verified
tags: [roadmap, async, transcoding]
links:
Expand All @@ -1260,17 +1263,28 @@ artifacts:
two-memory modules, asserting correct transcoded bytes + (for the
latin1+utf16 directions) the tagged length, for both latin1-fitting
and utf16-requiring strings, including the nested cases and the
nested-list<u8>-not-transcoded guarantee. The async-lift trampoline
INTEGRATION (the real callback/stackful adapter) is verified by the
inc*_{callback,stackful}_*_within_budget tests, which generate the
REAL adapter and assert local-index addressability — the
compensating control for the full async-lift e2e, which is gated on
nested-list<u8>-not-transcoded guarantee. The DEPTH-2
`list<list<string>>` recursion (#286) is verified by the runtime
oracles d5d_depth2_nested_list_list_string_{,param_}utf8_to_utf16_transcodes
(RESULT + PARAM, following the doubly relocated pointers and asserting
the deepest strings transcoded) and the allow-set boundary tests
d5d_async_nested_list_list_{string_result,string_param}_allowed plus
the negatives d5d_async_nested_list_list_u8_{result,param}_fail_loud and
d5d_async_nested_depth3_{result,param}_fail_loud (depth-3 stays loud).
The async-lift trampoline INTEGRATION (the real callback/stackful
adapter) is verified by the inc*_{callback,stackful}_*_within_budget AND
d5d_{callback,stackful}_adapter_depth2_nested_{result,param}_within_budget
tests, which generate the REAL adapter and assert local-index
addressability (catching budget overflow AND local-reuse collision) —
the compensating control for the full async-lift e2e, which is gated on
the kiln runtime (out of scope for this repo's tests, per the
existing async-lift fuse-only/structural posture). Each increment
passed an adversarial Mythos delta-pass; the passes caught four real
passed an adversarial Mythos delta-pass; the #272 passes caught four real
silent-corruption bugs before merge (callback budget overflow; the
nested list<u8> corruption blocker; the param_wit_types
per-pointer-pair index misalignment; the same-encoding UTF-16 nested
deep-copy under-copy). #281 (async nested-param pointers dangling
into caller memory) was closed in the same work.
deep-copy under-copy), and the #286 depth-2 passes confirmed the
recursion REFUTED across directions + aliasing/empty-inner edges. #281
(async nested-param pointers dangling into caller memory) was closed in
the same work.
milestone: post-v0.31.0
19 changes: 11 additions & 8 deletions safety/stpa/loss-scenarios.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1286,14 +1286,17 @@ loss-scenarios:
The async adapter emission path assumes both components share a string
encoding (true for same-encoding fusions) and has no branch for the
cross-encoding case — neither a transcoding emitter nor a loud rejection.
RESOLVED (#272 campaign, SR-41): async cross-encoding transcoding is now
implemented for all 6 directions × {param, result} × {flat, one-level
list/record/tuple nesting}. This guard remains as the RESIDUAL fallback:
it now fails loud ONLY for shapes still unsupported — currently deeper
list nesting (`list<list<string>>`, #286, a recursive-copy restructure) —
so any not-yet-transcodable cross-encoding string still fails loud rather
than silently raw-copying. The original blanket fail-loud (the safe
interim before #272) has been narrowed to exactly the unimplemented set.
RESOLVED (#272 campaign + #286, SR-41): async cross-encoding transcoding
is now implemented for all 6 directions × {param, result} × {flat,
one-level list/record/tuple nesting, AND two-level list nesting
`list<list<string>>` via codegen-time recursion}. This guard remains as
the RESIDUAL fallback: it now fails loud ONLY for shapes still
unsupported — currently deeper-than-two-level list nesting
(`list<list<list<string>>>`), bounded by the depth the emitter recurses
(one level) and the async-adapter local budget — so any not-yet-
transcodable cross-encoding string still fails loud rather than silently
raw-copying. The original blanket fail-loud (the safe interim before
#272) has been narrowed to exactly the unimplemented set.
status: approved
priority: high
fix: >
Expand Down
Loading