Skip to content

refactor(adapter): #286 5d-pre — type-carrying Indirection descriptor (no behavior change)#290

Open
avrabe wants to merge 1 commit into
mainfrom
feat/286-5d-pre-type-carrying-indirection
Open

refactor(adapter): #286 5d-pre — type-carrying Indirection descriptor (no behavior change)#290
avrabe wants to merge 1 commit into
mainfrom
feat/286-5d-pre-type-carrying-indirection

Conversation

@avrabe

@avrabe avrabe commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

What & why

collect_indirections returned a flat Vec<(offset, sub_elem_size, is_string)> that treated CVT::List(elem) as one is_string=false leaf and discarded the element type. That discard is the structural blocker for depth-N nested-string transcoding (#286 5d — list<list<string>>): the emitter can't recurse into an inner pointer-bearing list if the descriptor never told it the list's element type.

This is 5d-pre: a behaviour-preserving descriptor redesign that carries the type, setting up 5d cleanly.

Change

struct Indirection { offset, sub_elem_size, kind }
enum IndirectionKind { String, List { elem: Box<ComponentValType> } }  // elem = the 5d recursion seam
Indirection::is_string() == matches!(kind, String)                     // the former flag

All consumer sites moved to field access (offset/sub_elem_size kept as references so *offset/*sub_elem_size body reads are untouched):

  • emit_patch_nested_indirections (result), emit_param_nested_indirections (param)
  • the 4 guard allow-predicate closures → .all(|ind| ind.is_string())
  • lib.rs async result shim-stabilization deep-copy + its &[Indirection] param

No behaviour change (the 5d-pre invariant)

Both list<list<string>> and list<list<u8>> still collect to a single List leaf with is_string() == false, so the guard's .all(is_string) predicate still rejects them → they stay fail-loud (SAFE), exactly as before. 5d-pre only adds the carried elem; it does not widen the allow-set. elem is #[allow(dead_code)] until 5d consumes it.

Verification

  • New unit test collect_indirections_carries_nested_list_element_type_5d_pre pins the descriptor (list<string> vs list<u8>, depth-1 vs depth-2) and reads the carried elem, proving the type is genuinely carried.
  • Full meld-core suite green — incl. 44 async_cross_encoding + 23 adapter_safety nested/SR-17 oracles (the behaviour-preservation oracle).
  • clippy --all-targets -D warnings clean; fmt clean; LS-N gate 57/0/0.

Scope

Tier-5 (adapter/fact.rs, lib.rs) → Mythos clean-room delta-pass + mythos-pass-done label before merge.

🤖 Generated with Claude Code

… (no behavior change)

`collect_indirections` returned a flat `Vec<(offset, sub_elem_size, is_string)>`
that treated `CVT::List(elem)` as ONE `is_string=false` leaf and DISCARDED the
element type — so the emitter could never know an inner indirection is itself a
pointer-bearing list needing recursion. That discard is the structural blocker
for depth-N nested-string transcoding (#286 5d / list<list<string>>).

Replace the tuple with a type-carrying descriptor:
  struct Indirection { offset, sub_elem_size, kind }
  enum IndirectionKind { String, List { elem: Box<ComponentValType> } }
  Indirection::is_string() == matches!(kind, String)   // the former flag

The `List { elem }` leaf now CARRIES the inner element WIT type — the 5d
recursion seam. `elem` is `#[allow(dead_code)]` until 5d wires in the recursive
copy (5d-pre is behaviour-preserving by construction).

Updated all consumer sites to field access (offset/sub_elem_size kept as
references so `*offset`/`*sub_elem_size` body reads are unchanged):
  - emit_patch_nested_indirections (result), emit_param_nested_indirections (param)
  - the 4 guard allow-predicate closures (.all(|ind| ind.is_string()))
  - lib.rs async result shim-stabilization deep-copy + its &[Indirection] param

NO behaviour change: both list<list<string>> and list<list<u8>> still collect to
a single List leaf with is_string()==false, so the guard's .all(is_string)
predicate still rejects them and they stay fail-loud (SAFE) — exactly as before.

Oracles: new unit test collect_indirections_carries_nested_list_element_type_5d_pre
pins the descriptor (list<string> vs list<u8>, depth-1 vs depth-2) and READS the
carried elem; full meld-core suite green (incl. 44 async_cross_encoding + 23
adapter_safety nested/SR-17 oracles); clippy -D warnings clean; fmt clean;
LS-N gate green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Mythos delta-pass required

This PR modifies one or more Tier-5 source files (per
scripts/mythos/rank.md):

meld-core/src/adapter/fact.rs

Before merge, run the Mythos discover protocol on the
modified Tier-5 files:

  1. Follow scripts/mythos/discover.md
    — one fresh agent session per touched Tier-5 file.
  2. For each finding, the agent must produce both a Kani
    harness and a failing PoC test (per the protocol's
    "if you cannot produce both, do not report" rule).
  3. Attach a comment on this PR with either the findings
    (formatted per discover.md's output schema) or
    NO FINDINGS.
  4. Add the mythos-pass-done label to this PR.

Why this gate exists: LS-A-10
(CABI alignment padding in async-lift retptr writeback) was
found by the v0.8.0 pre-release Mythos pass — but it had
lived in the callback emitter since #128, across six
releases. A PR-time gate would have caught it at review
time instead of at the release boundary.

The gate check on this PR will pass once the label is
applied.

@github-actions

Copy link
Copy Markdown

LS-N verification gate

57/57 approved LS entries verified

count
Passed (≥1 test, all green) 57
Failed (≥1 test failure) 0
Missing (no ls_*_NN_* test found) 0

Approved loss-scenarios.yaml entries are expected to have a
regression test named ls_<letter>_<num>_* (e.g. LS-A-11
ls_a_11_*). The gate runs each prefix via cargo test --lib --no-fail-fast and aggregates pass/fail/missing.

Failed LS entries

(none)

Missing regression tests

(none)

Updated automatically by tools/post_verification_comment.py.
Source of truth: safety/stpa/loss-scenarios.yaml.

@github-actions

Copy link
Copy Markdown

Mythos delta-pass (auto)

NO FINDINGS across 1 Tier-5 file(s)

File Verdict Hypothesis
`` ✅ NO FINDINGS

Auto-run via anthropics/claude-code-action@v1
(SHA-pinned) on the touched Tier-5 files, using the
maintainer's Max-plan OAuth token. See
.github/workflows/mythos-auto.yml and
scripts/mythos/discover.md.

@github-actions github-actions Bot added the mythos-pass-done Mythos delta-pass completed on Tier-5 file changes; findings (or NO FINDINGS) attached to PR label Jun 15, 2026
@avrabe

avrabe commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Status — pre-merge gating

Required CI: Clippy / Format / LS-N (57/0/0) / Coverage / Detect-Tier-5 → all green.

Non-blocking:

  • Fuzz smoke (4 jobs) fail with ToolNotFound: x86_64-linux-musl-g++ — the known smithy: sanitizer/libc config drift recurrence on fuzz smoke jobs #168 musl/sccache infra flake on the runner, not a code failure and not a required gate.
  • Mythos delta-pass gate fails pre-label as expected; it goes green once the clean-room Tier-5 pass completes and the mythos-pass-done label fires the labeled webhook.

Merge is gated on the Mythos clean-room delta-pass (Tier-5 discipline). That adversarial pass is queued; the model API is transiently overloaded (529), so it will run on the next attempt. Inline pre-audit (compiler-verified complete under -D warnings; the 44 async_cross_encoding + 23 adapter_safety runtime oracles covering the exact touched emitter/guard paths all pass) supports behaviour-preservation, but the fresh-context adversarial pass is still required before the label is applied.

Not merging until the clean-room pass returns REFUTED.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mythos-pass-done Mythos delta-pass completed on Tier-5 file changes; findings (or NO FINDINGS) attached to PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant