ADR-015 S6a: WIT export lifting for WASI command components#343
Merged
Conversation
…oke)
Lift a parameter-less `fn main()` into the WASI 0.2 (preview2) command
shape so `wasmtime run <component>` actually runs an AffineScript
program end-to-end, closing the "real-host main-invoke" gap left open
by S3 (reactor-only componentize) and S4a/b (preview1 import bridging).
Codegen (lib/codegen.ml):
- After exports_with_mem is assembled, when `main` is exported and
takes no parameters, append a `_start : () -> ()` shim whose body
is `Call main_idx; Drop` (drops main's i32 result — current ABI is
uniformly i32-returning even for `() -> ()`). Skips silently if a
user already exports `_start` or `main` has parameters.
- Purely additive: every existing consumer (reactor componentize,
game-loop hosts, `__indirect_function_table` for closures) sees the
same exports plus an extra `_start`. Lambda-table elem indices are
unaffected (start_func is appended after lambdas in all_funcs).
Tooling:
- tools/provision-component-toolchain.sh now fetches both the reactor
and command adapters (wasmtime v44.0.1), each sha256-pinned and
fail-closed. Back-compat: the S3-era `ADAPTER_URL`/`_SHA256`/`_PATH`
variables remain as reactor-aliased exports.
- tools/componentize.sh learns `--command` / `--reactor` modes;
`--command` selects the command adapter, fails fast with a pointer
to the codegen contract if the core is missing `_start`, and
asserts `wasi:cli/run` is exported in the resulting component.
Gate:
- tests/componentize/command_smoke.sh — opt-in, SKIPs cleanly without
the toolchain or wasmtime; otherwise compiles a fixture, asserts the
`_start` shim, runs the command componentize path, asserts the
ownership section survives + `wasi:cli/run` is lifted, and runs the
component under `wasmtime run` (exit 0 is the contract).
Verified end-to-end on this branch: `wasmtime run` succeeds on a
real fresh-compiled component (`fn consume(x) { x }` /
`fn main() { consume(42) }`), the existing S3 reactor smoke still
passes, and the full OCaml test suite stays green (295 tests).
Docs:
- TECH-DEBT.adoc / ECOSYSTEM.adoc INT-03 rows: S6 split into S6a
(WIT export lifting, DONE) + S6b (sockets) + S6c (default-flip).
- META.a2ml ADR-015 decision text mirrors the split.
- SETTLED-DECISIONS.adoc mirror updated in lockstep.
WIT world (`wit/affinescript.wit`) unchanged — already the contract
of record; the command-mode output exports a subset (`wasi:cli/run`
plus the adapter's required imports). Sockets + default-target flip
remain in scope for S6b/S6c per the ADR.
Refs #180
🔍 Hypatia Security ScanFindings: 143 issues detected
View findings[
{
"reason": "Stray AI.a2ml in root -- use 0-AI-MANIFEST.a2ml only",
"type": "banned",
"file": "AI.a2ml",
"action": "delete",
"rule_module": "root_hygiene",
"severity": "high"
},
{
"reason": "Superseded by 0-AI-MANIFEST.a2ml",
"type": "banned",
"file": "AI.djot",
"action": "delete",
"rule_module": "root_hygiene",
"severity": "high"
},
{
"reason": "Issue in quality.yml",
"type": "missing_workflow",
"file": "quality.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in security-policy.yml",
"type": "missing_workflow",
"file": "security-policy.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
"type": "unpinned_action",
"file": "governance.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Action actions/checkout@v6 needs attention",
"type": "unpinned_action",
"file": "publish-jsr.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action denoland/setup-deno@v2 needs attention",
"type": "unpinned_action",
"file": "publish-jsr.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/example/smoke_driver.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/cli.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
🔍 Hypatia Security ScanFindings: 142 issues detected
View findings[
{
"reason": "Stray AI.a2ml in root -- use 0-AI-MANIFEST.a2ml only",
"type": "banned",
"file": "AI.a2ml",
"action": "delete",
"rule_module": "root_hygiene",
"severity": "high"
},
{
"reason": "Superseded by 0-AI-MANIFEST.a2ml",
"type": "banned",
"file": "AI.djot",
"action": "delete",
"rule_module": "root_hygiene",
"severity": "high"
},
{
"reason": "Issue in quality.yml",
"type": "missing_workflow",
"file": "quality.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in security-policy.yml",
"type": "missing_workflow",
"file": "security-policy.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
"type": "unpinned_action",
"file": "governance.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Action actions/checkout@v6 needs attention",
"type": "unpinned_action",
"file": "publish-jsr.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action denoland/setup-deno@v2 needs attention",
"type": "unpinned_action",
"file": "publish-jsr.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/example/smoke_driver.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/cli.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements ADR-015 S6a (WIT export lifting) to enable AffineScript programs to be invoked as WASI commands via
wasmtime runand other WASI 0.2 hosts. When a parameter-lessfn main()is present, the compiler now auto-emits a_start : () -> ()shim that callsmainand drops its result, allowing the command adapter to lift this into awasi:cli/runexport.Key Changes
Compiler (lib/codegen.ml)
_start : () -> ()shim whenever a parameter-lessfn main()is presentmainand drops its i32 result viaDropinstructions__indirect_function_tableexports are byte-unchanged_startalready exists ormainhas parametersToolchain (tools/provision-component-toolchain.sh)
ADAPTER_COMMAND_URLandADAPTER_COMMAND_SHA256(8ff2ea78d31179f12d6fb1d2cadc0ab83356cd049f362d5a8d94a4070c7a15bd)fetch_adapter()functionADAPTER_URL,ADAPTER_SHA256,ADAPTER_PATH) pointing to reactorComponentizer (tools/componentize.sh)
--commandand--reactormode flags (reactor is default)_startexport presence in command mode (fail-fast with pointer to codegen contract)wasi:cli/runexport exists in command mode (catches adapter/lift regressions)Testing (tests/componentize/command_smoke.sh)
main, componentizes with--commandwasi:cli/runexport,wasmtime runinvocation succeeds (exit 0), ownership section survivesDocumentation
Implementation Details
_startshim is inserted as a new function in the module's function list, with its index recorded in the exports() -> ()type is reused if it already existsCalltomainfollowed byDropinstructions for each result typewasm-tools printto check for_startexport andwasm-tools component witto verify the lifthttps://claude.ai/code/session_01NK8KaMbWEwJZfvmrq8Nm8X