Skip to content

docs(proposals): add 0003 [draft] — typedwasm.region-imports (L13 cross-module)#112

Merged
hyperpolymath merged 1 commit into
mainfrom
proposal-0003-region-imports
May 30, 2026
Merged

docs(proposals): add 0003 [draft] — typedwasm.region-imports (L13 cross-module)#112
hyperpolymath merged 1 commit into
mainfrom
proposal-0003-region-imports

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Closes #95's third acceptance bullet ("if [draft] proposal 0003 is authored, it tracks back here"). Closes the latent seam flagged in proposal 0001 §"Open questions" #5 (cross-module region foreign keys) and the symmetric gap noted in proposal 0002 §"Open questions" #3.

What 0003 specifies

A third producer-neutral carrier (slotting between 0001's regions/capabilities and 0002's access-sites):

  • typedwasm.region-imports carries per-module table of imported regions: source module name, region name, expected schema (for cross-module schema-agreement verification).
  • Companion non-breaking extension to typedwasm.regions: target_region foreign keys gain a high-bit convention for import-table indices:
    • 0x00000000..0x7FFFFFFE — local region index
    • 0x80000000..0xFFFFFFFE — imported region (index = value - 0x80000000)
    • 0xFFFFFFFFScalar sentinel (unchanged)

v1 typedwasm.regions consumers see "region_id out of range" on high-bit values and recover via lenient codec; v1.1 consumers interpret the high bit as import-table indicator. No wire breaking change.

Wire format

Mirrors 0001/0002/0004 conventions (LEB128 per field, UTF-8 strings, lenient on truncation):

u16le         version                (= 1)
u32le_leb128  import_count
for each import:
    u32le_leb128  producer_module_name_len
    u8[]          producer_module_name      (wasm module name)
    u32le_leb128  region_name_len
    u8[]          region_name               (exported region name)
    u32le_leb128  expected_field_count
    for each expected field:
        u32le_leb128  field_name_len
        u8[]          field_name
        u8            kind                  (FieldKind: Scalar only in v1)
        u8            wasm_ty               (same enum as regions)
        u8            nullability
        u32le_leb128  cardinality

Section structure

Section Coverage
Context L13 cross-module gap in 0001, MultiModule.idr spec already covers it, latent-seam framing
Proposal high-bit target_region extension; wire format; spec-type mapping; versioning; producer/consumer obligations; coordination
Producer obligations 6 items (companion regions section mandatory, high-bit convention, wasm-module-name matching, omit-if-empty, no-pointer-fields-in-v1, only-real-imports)
Consumer obligations verify_region_imports_from_module pass + 7 error variants (MissingDependentRegions, DuplicateImport, UnresolvedProducerModule, UnresolvedExportedRegion, SchemaImportMismatch, ImportTargetOutOfRange, PointerInImportNotSupportedInV1)
Alternatives considered B extend-regions (rejected — conflates concerns); C component-model (deferred); D wasm-imports (rejected — confuses linkers); E string-table (deferred to v2)
Open questions (1) pointer-typed expected fields (deferred); (2) cross-module access sites — recommend folding 0002 §OQ3 in; (3) cross-module capability grants (0004 §OQ4 — may differ); (4) link-time vs verify-time (default: separate verify_link_graph pass); (5) producer module name normalisation (NFC deferred); (6) empty import table semantics
Acceptance criteria 6 gates mirroring 0001/0002/0004

Spec-side mapping

Realises MultiModule.idr's:

Idris2 type Wire realisation
ImportedRegion.source (line 54) producer_module_name
ImportedRegion.regionName (line 56) region_name
ImportedRegion.expectedSchema (line 57) per-field table
SchemaSub (line 249) verifier reconstructs from wire + producer's regions
ModuleCompat from to imp exp (line 318) verifier output (one per resolved import)
noSpoofing (line 374, flagship) the L13 property the verifier realises on emitted bytes
CompatCertificate (line 142) verifier-emitted per resolved import
SchemaMismatch (line 185) SchemaImportMismatch error variant

Why [draft] not [review]

Neither producer can emit typedwasm.region-imports today:

  • AffineScriptlib/tw_interface.ml has cross-module verification scaffolding for L10/L13 boundary (reads typedwasm.ownership cross-module), but Roadmap C3 (multi-module region emission) is the prerequisite.
  • Ephapax — cross-module region emission isn't on the roadmap yet; src/ephapax-wasm/ is single-module.

README update

Adds 0003 entry to docs/proposals/README.adoc's "Current proposals" table; removes the "Proposal 0003 ... reserved" note (now occupied).

Test plan

  • AsciiDoc renders cleanly (cols-tables, code-blocks, cross-refs).
  • Cross-references resolve (MultiModule.idr line numbers; sibling proposal links; tracker issue links).
  • Rebased onto main after PR docs(proposals): add 0004 [draft] — typedwasm.capability-grants (L15-C) #111 merge (no conflicts).
  • No code changes — no Cargo build required.
  • Reviewer cross-check: confirm the high-bit target_region convention doesn't break any v1 consumer (existing tests).

Related

🤖 Generated with Claude Code

…ss-module)

Closes #95's third acceptance bullet ("if [draft] proposal 0003 is
authored, it tracks back here"). Closes the latent seam flagged in
proposal 0001 §"Open questions" #5 and the symmetric gap noted in
proposal 0002 §"Open questions" #3.

## What 0003 specifies

A third producer-neutral carrier (slotting between 0001's
regions/capabilities and 0002's access-sites): typedwasm.region-imports
carries per-module table of imported regions (source module name,
region name, expected schema). Companion to typedwasm.regions which
gains a non-breaking high-bit convention for target_region foreign
keys:

- 0x00000000..0x7FFFFFFE: local region index
- 0x80000000..0xFFFFFFFE: imported region (index = value - 0x80000000)
- 0xFFFFFFFF: Scalar sentinel (unchanged)

v1 typedwasm.regions consumers see "region_id out of range" on
high-bit values and recover via lenient codec; v1.1 consumers
interpret the high bit as import-table indicator.

## Wire format

Mirrors 0001/0002/0004 wire conventions (LEB128 per field, UTF-8
strings, lenient on truncation):

  u16le         version                (= 1)
  u32le_leb128  import_count
  for each import:
      u32le_leb128  producer_module_name_len
      u8[]          producer_module_name      (wasm module name)
      u32le_leb128  region_name_len
      u8[]          region_name               (exported region name)
      u32le_leb128  expected_field_count
      for each expected field:
          u32le_leb128  field_name_len
          u8[]          field_name
          u8            kind                  (FieldKind: Scalar only in v1)
          u8            wasm_ty               (same enum as regions)
          u8            nullability
          u32le_leb128  cardinality

## Spec-side mapping

Realises MultiModule.idr's ImportedRegion (line 53), SchemaSub (249),
ModuleCompat (318), and the flagship noSpoofing theorem (374).
Verifier constructs ModuleCompat from emitted bytes by parsing both
modules' carriers and checking SchemaSub expected actual.

## 7 error variants

MissingDependentRegions, DuplicateImport, UnresolvedProducerModule,
UnresolvedExportedRegion, SchemaImportMismatch, ImportTargetOutOfRange,
PointerInImportNotSupportedInV1.

## 6 open questions sequenced

(1) Pointer-typed expected fields (deferred to v2 — needs SchemaSub
to recurse into pointer targets); (2) cross-module access sites (0002
§OQ3 — same high-bit convention extends naturally; recommend folding
in at [review]); (3) cross-module capability grants (0004 §OQ4 —
capabilities are name-keyed, may resolve differently); (4) link-time
vs verify-time resolution (default: separate verify_link_graph pass);
(5) producer module name normalisation (NFC deferred to v2); (6)
empty import table semantics (omit section entirely recommended).

## Section structure

Standard: Context | Proposal (extension + wire format + spec mapping +
versioning + producer/consumer obligations + coordination) |
Alternatives considered (B extend regions / C component-model / D
wasm-imports / E string-table) | Open questions (6 above) | Acceptance
criteria (6 gates mirroring 0001/0002/0004) | Related.

## Why [draft] not [review]

Neither producer can emit typedwasm.region-imports today. AffineScript
has cross-module verification scaffolding (lib/tw_interface.ml for
L10/L13 boundary) but Roadmap C3 (multi-module region emission) is
the prerequisite. Ephapax cross-module region emission isn't on the
roadmap yet.

## README update

Adds 0003 entry to docs/proposals/README.adoc's "Current proposals"
table. Removes the "Proposal 0003 ... reserved" note (now occupied).

Refs: #34, #50, #95, #106, PR #37 (L13 single-module), PR #76
(proposal 0001 with the deferral), MultiModule.idr (entire spec —
ImportedRegion through SchemaMismatch).

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

🔍 Hypatia Security Scan

Findings: 96 issues detected

Severity Count
🔴 Critical 8
🟠 High 19
🟡 Medium 69

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action perpolymath/standards/.github/workflows/governance-reusable.yml@main\n needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in boj-build.yml",
    "type": "unknown",
    "file": "boj-build.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in c5-regenerate.yml",
    "type": "unknown",
    "file": "c5-regenerate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in cargo-audit.yml",
    "type": "unknown",
    "file": "cargo-audit.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in codeql.yml",
    "type": "unknown",
    "file": "codeql.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "unknown",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "unknown",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "unknown",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "unknown",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "unknown",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath merged commit bea28fa into main May 30, 2026
31 checks passed
@hyperpolymath hyperpolymath deleted the proposal-0003-region-imports branch May 30, 2026 14:43
hyperpolymath added a commit that referenced this pull request May 30, 2026
## Summary

Closes [#94](#94) —
the only remaining open question on proposal 0001 before `[review] →
[accepted]` flip.

**Decision: WBool is 4 bytes on the wire** (i32.store/load; 0 = false,
nonzero = true). The narrower 1-byte encoding is reserved for a future
`WBoolPacked` variant in v2.

## Two changes

| File | Change |
|---|---|
| `docs/proposals/0001-multi-producer-carrier-section.adoc` | New
`§"WBool wire width — pinned at 4 bytes"` subsection (~36 LOC) inside
`§"Wire format — typedwasm.regions"`. Documents rationale, reserves
`WBoolPacked` v2, references the rejected lenient alternative. |
| `src/abi/TypedWasm/ABI/Region.idr` | `sizeOf WBool = 4` (was `1`) with
inline comment pointing at the proposal text and producer-side evidence
files. |

## Why 4-byte, not 1-byte, not mixed-width

1. **Producer reality**: both shipping producers already emit 4-byte
`i32.store` for boolean fields (AffineScript
`lib/codegen.ml:180-190+:373`; Ephapax
`src/ephapax-wasm/src/lib.rs:2937-2944`). Pinning at 4 = zero codegen
changes.
2. **Spec self-consistency**: `Region.idr` was the outlier at 1 byte;
this PR brings spec into alignment with producer reality. `alignOf =
sizeOf` (Region.idr:113) carries through to field-alignment math. No
proofs or tests hardcode `WBool=1` — verified by grep.
3. **Verifier simplicity**: single canonical width means no new
`MixedWidthBoolean` error variant; `region_byte_size` cross-check is
deterministic per schema.
4. **Future flexibility**: a 1-byte `WBoolPacked` (or named-equivalent)
remains the v2 escape hatch as a new `WasmType` constructor, NOT a width
flag on the existing `WBool` codepoint. Additive, not breaking.

## Rejected: lenient mixed-width

The `§A` sketch in #94's recommendation (allow either width per field,
validate consistency) is rejected because:

- `region_byte_size` becomes producer-choice-dependent — same schema →
different `schemaSize` values
- Forces a new `MixedWidthBoolean` verifier error variant for marginal
flexibility
- Complicates cross-module schema agreement: a 1-byte WBool field in one
module is structurally incompatible with a 4-byte WBool field of the
same name in another module

## Risk assessment

- Idris2 `sizeOf` change cascades to `schemaSize` / `computeOffsets` /
`alignOf` — none of these is hardcoded against `WBool=1` in any test or
proof. `MultiModule.idr`'s `Example` schema uses WBool but only via
`SchemaEq`/`SchemaSub` structural relations.
- `TypedAccess.idr:51` (`HostType WBool = Bool`) is host-side type
mapping; unaffected by wire width.
- `crates/typed-wasm-verify` `region_byte_size` validation is currently
`MAY cross-check` (not enforced) — when implemented later, the canonical
4-byte rule makes the check deterministic.

## Acceptance update for #94

- [x] Proposal 0001 amended with explicit `WBool` wire width.
- [n/a] No `MixedWidthBoolean` error variant (strict resolution chosen).
- [x] Forward-pointer to `WBoolPacked` future-extension added.

## What this means for 0001 [review] → [accepted]

This was the last load-bearing open question on proposal 0001. After
merge:

| Acceptance gate | State |
|---|---|
| Criterion 1 (producer signoff) | ✅ |
| Criterion 2 (wire↔spec mapping) | ✅ Appendix A (PR #110) |
| Criterion 3 (draft codec) | ✅ PR #107 |
| Criterion 4 (draft spec doc) | ✅ PR #108 |
| Criterion 5 (cross-repo issues filed) | ✅ affinescript#444 +
ephapax#221 |
| OQ #94 (WBool width) | ✅ **this PR** |
| OQ #95 (region-imports) | ✅ proposal 0003 [draft] (PR #112) |
| OQ #96 (capability-grants) | ✅ proposal 0004 [draft] (PR #111) |

Proposal 0001 is **fully ready for `[accepted]`** after this lands —
owner decision is the only remaining step.

## Test plan

- [x] `git grep` confirms no hardcoded `WBool=1` size assertions in
proofs or tests.
- [x] `sizeOf WBool` only used via
`computeOffsets`/`alignOf`/`fieldSize` (derived, not hardcoded).
- [ ] Idris2 build passes (CI will verify).
- [ ] Cargo build + test passes (no Rust code changes — should be a
no-op).

## Related

- #94 (this PR closes it)
- #106 (acceptance roadmap tracker)
- #34 (proposal 0001 umbrella)
- ephapax#165 §2-Q1 / affinescript#402 §3-Q1 — paired producer reviews
- PR #76 (proposal 0001 original landing)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 30, 2026
…loses #97) (#114)

## Summary

Closes [#97](#97) —
addresses both halves of the paired-review meander finding.

## (A) Producer-readiness checklist — Appendix B in proposal 0001 (~120
LOC)

Tabulates each carrier section's IR prerequisites, current producer-side
status, and roadmap-issue identifier in each producer's tracker where
the gap is named:

| Carrier | IR prerequisites | Status |
|---------|-----------------|--------|
| `typedwasm.ownership` | per-fn ownership-kind tracking | **SHIPPING**
|
| `typedwasm.regions` | region decls + field offsets + stable indices |
**NOT YET EMITTABLE** (AS Roadmap C1 deferred; Ephapax dead code) |
| `typedwasm.capabilities` | per-fn cap decl + module budget + effect IR
| **NOT YET EMITTABLE** (AS Roadmap C2 not started; Ephapax
Perform/Handle stubbed) |
| `typedwasm.region-imports` (0003) | + cross-module region tracking +
wasm-module-name resolution | **NOT YET EMITTABLE** |
| `typedwasm.access-sites` (0002) | + per-instr tracking + post-rewrite
hook | **NOT YET EMITTABLE** (depends on regions) |
| `typedwasm.capability-grants` (0004) | + per-callsite grant tracking |
**NOT YET EMITTABLE** (depends on capabilities) |

NOTE block surfaces the all-or-nothing implication: **do not emit a
section you cannot populate.**

Proposal 0002 gains a §"Producer-readiness (cross-reference)" subsection
(~28 LOC) pointing to 0001's Appendix B plus three access-sites-specific
items: per-instruction tracking, post-rewrite hook discipline,
region-index stability across sections.

## (B) Canonical emit ordering — extends 0001 §"Producer obligations"

New 5th item specifying the recommended emit order matching the runtime
dependency graph:

```
1. typedwasm.ownership
2. typedwasm.regions
3. typedwasm.region-imports        (proposal 0003)
4. typedwasm.capabilities
5. typedwasm.access-sites          (proposal 0002)
6. typedwasm.capability-grants     (proposal 0004)
```

**Consumers MUST NOT depend on this order** — the verifier reads
sections by custom-section name, so any order is parseable. The
canonical order exists for cross-producer module comparability
(byte-equal carrier sequences for two producers of the same logical
module — useful for `cmp` / `diff` / content-addressing).

## Acceptance update for #97

- [x] Proposal 0001 gains §"Producer-readiness checklist" appendix
listing the IR prerequisites for each section.
- [x] Proposal 0002 gains a one-line cross-reference (expanded to a full
subsection with access-sites-specific items) to 0001's checklist.
- [x] Proposal 0001 §"Producer obligations" specifies the canonical emit
order with a "consumer MAY accept any order" note.
- [ ] When AffineScript / Ephapax start their respective Roadmap
C1/C2/C3 implementations, those issues cross-reference this checklist.
*(Producer-side action, not a typed-wasm gate.)*

## What this closes

Together with #94, #95, #96 (resolved in PRs #110/#111/#112/#113), this
completes all the documentation-side gates around proposals 0001 and
0002. Both proposals are now fully ready for `[review] → [accepted]`
owner decision.

## Test plan

- [x] AsciiDoc renders cleanly (cols-tables, lower-alpha sub-list,
code-block fences).
- [x] Cross-reference link to Appendix B from proposal 0002 uses
AsciiDoc anchor format.
- [x] No code changes — no Cargo/Idris2 build required.

## Related

- #97 (this PR closes it)
- #34 (proposal 0001 umbrella)
- #106 (acceptance roadmap tracker)
- ephapax#165 §3+§6 / affinescript#402 §4+§7 — paired reviews surfacing
the gap
- affinescript#462 (access-sites codegen issue — referenced from
Appendix B)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 30, 2026
…115)

## Summary

Owner-decision close of the proposal-acceptance arc. Both proposals
satisfied every acceptance gate this session ([see #106 wrap-up
comment](#106 (comment)));
this PR applies the status flip.

## Status changes

- `docs/proposals/0001-multi-producer-carrier-section.adoc` — `review →
accepted`
- `docs/proposals/0002-access-site-carrier.adoc` — `review → accepted`
- `docs/proposals/README.adoc` — "Current proposals" table updated; NOTE
block clarifies files remain in `docs/proposals/` (ADR promotion is a
separate file-restructure follow-up).

## LEVEL-STATUS.md updates

| Level | Before | After |
|-------|--------|-------|
| L2 (region binding) | proposal-stage | **YES** (carrier-backed) —
`verify_access_sites_from_module` (PR #109); gated `unstable-l2` |
| L3–L6 (type-compat, null, bounds, result-type) | proposal-stage |
**YES** (carrier-backed, schema half) — regions codec PR #107;
per-access enforcement gated on producer codegen |
| L15-A/B (capabilities) | proposal-stage | **YES** (carrier-backed) —
`verify_capabilities_from_module` (PR #109); gated `unstable-l15` |
| L13 cross-module (positive form) | — | proposal-stage — proposal 0003
`[draft]` (new row) |

"Open gating items" section rewritten to remove obsolete pre-acceptance
gates (all shipped via #107/#109) and enumerate the remaining
producer-side prerequisites + [draft] proposal 0003/0004 work.

## What this DOES NOT change

- **File locations**: proposals stay in `docs/proposals/`. ADR promotion
to `docs/decisions/` (with renumbering — existing ADR 0001 is
"adopt-rsr-standard", so proposals 0001/0002 would become ADRs
0002/0003) is a deliberate separate PR to keep the status flip cleanly
auditable.
- **Code**: no source or test changes. Verifier passes already shipped
in #107/#109 behind `unstable-l2` / `unstable-l15` feature flags.
- **Producer-side codegen**: still pending per Appendix B prerequisites
in proposal 0001.

## Test plan

- [x] Status field flipped on both proposals.
- [x] README table reflects new statuses with date.
- [x] LEVEL-STATUS L2/L3-L6/L15 rows show carrier-backed YES.
- [x] Open gating items rewritten (4 items: producer codegen, L13
cross-module, L15-C, ADR promotion).
- [ ] CI passes (doc-only changes; no Cargo/Idris2 build risk).

## Related

- #34 (proposal 0001 umbrella)
- #78 (proposal 0002 RFC)
- #106 (acceptance roadmap tracker — full wrap-up comment)
- This session's 5-PR sprint that satisfied every gate: #107 (codec),
#108 (spec doc), #109 (verifier), #110 (Criterion 2 appendix), #111
(proposal 0004 draft for #96), #112 (proposal 0003 draft for #95), #113
(WBool pin for #94), #114 (producer-readiness for #97).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tracking: proposal 0003 — typedwasm.region-imports (cross-module region foreign keys)

1 participant