Skip to content

Commit ab3db11

Browse files
committed
Merge branch 'main' into claude/happy-mendel-b4IeU and resolve TECH-DEBT conflicts
2 parents e065d10 + b0b0a22 commit ab3db11

40 files changed

Lines changed: 1697 additions & 182 deletions

.github/workflows/ci.yml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,16 +287,22 @@ jobs:
287287
# ReScript source. Picks the existing res-to-affine test fixture
288288
# so any drift in the pinned commit's syntactic surface area
289289
# surfaces here rather than at walker-rule writing time.
290+
#
291+
# NOTE: tree-sitter-cli >= 0.25 repurposed `--paths` to mean "a
292+
# file listing input source paths", not "a directory containing
293+
# a grammar". Grammar lookup is now driven by the current
294+
# working directory (the CLI walks up looking for grammar.js /
295+
# src/parser.c), so we cd into the vendored grammar tree and
296+
# pass an absolute path to the fixture. Without this, the step
297+
# fails with `Failed to read paths file ... Is a directory`.
290298
run: |
291299
shopt -s nullglob
292300
fixtures=(tools/res-to-affine/test/fixtures/*.res)
293301
if [ ${#fixtures[@]} -eq 0 ]; then
294302
echo "no .res fixtures to smoke-parse; skipping"
295303
exit 0
296304
fi
297-
tree-sitter parse \
298-
--quiet \
299-
"${fixtures[0]}" \
300-
--paths tools/vendor/tree-sitter-rescript \
301-
> /dev/null
305+
fixture_abs="$(realpath "${fixtures[0]}")"
306+
( cd tools/vendor/tree-sitter-rescript \
307+
&& tree-sitter parse --quiet "${fixture_abs}" > /dev/null )
302308
echo "smoke-parsed: ${fixtures[0]}"

.github/workflows/codeql.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ jobs:
3939
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
4040

4141
- name: Initialize CodeQL
42-
uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v3.28.1
42+
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.28.1
4343
with:
4444
languages: ${{ matrix.language }}
4545
build-mode: ${{ matrix.build-mode }}
4646

4747
- name: Perform CodeQL Analysis
48-
uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v3.28.1
48+
uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.28.1
4949
with:
5050
category: "/language:${{ matrix.language }}"

.github/workflows/hypatia-scan.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ jobs:
105105
echo "- Medium: $MEDIUM" >> $GITHUB_STEP_SUMMARY
106106
107107
- name: Upload findings artifact
108-
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
108+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
109109
with:
110110
name: hypatia-findings
111111
path: hypatia-findings.json
@@ -241,7 +241,7 @@ jobs:
241241
always() &&
242242
(github.event_name != 'pull_request' ||
243243
github.event.pull_request.head.repo.fork != true)
244-
uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v3.28.1
244+
uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.28.1
245245
with:
246246
sarif_file: hypatia.sarif
247247
# Distinct category so Hypatia results coexist with CodeQL's
@@ -381,7 +381,7 @@ jobs:
381381
# the pull-requests: write permission above: a token/API hiccup or
382382
# a fork PR (read-only token) skips the comment, not the check.
383383
continue-on-error: true
384-
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7
384+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v7
385385
with:
386386
script: |
387387
const fs = require('fs');

.github/workflows/publish-jsr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
publish:
3939
runs-on: ubuntu-latest
4040
steps:
41-
- uses: actions/checkout@v4
41+
- uses: actions/checkout@v6
4242
- uses: denoland/setup-deno@v2
4343
with:
4444
deno-version: v2.x

.github/workflows/scorecard-enforcer.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
publish_results: true
3939

4040
- name: Upload SARIF
41-
uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v3
41+
uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3
4242
with:
4343
sarif_file: results.sarif
4444

.github/workflows/scorecard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ jobs:
3535
results_format: sarif
3636

3737
- name: Upload results
38-
uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v3.31.8
38+
uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.31.8
3939
with:
4040
sarif_file: results.sarif

.github/workflows/semgrep.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
3030

3131
- name: Upload SARIF
32-
uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
32+
uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
3333
with:
3434
sarif_file: semgrep.sarif
3535
if: always()

.github/workflows/workflow-linter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
lint-workflows:
1717
runs-on: ubuntu-latest
1818
steps:
19-
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
19+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
2020

2121
- name: Check SPDX headers
2222
run: |

.machine_readable/6a2/META.a2ml

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -988,8 +988,20 @@ Staged plan (ledger INT-03; each row = one gated PR):
988988
- S4: native `wasi:clocks` + environment + argv via preview2 (wasmtime
989989
host-testable), replacing the preview1 shims behind the component path.
990990
- S5: `wasi:filesystem` (open/read/write/close) — unblocks INT-06.
991-
- S6: `wasi:sockets`; then flip the default wasm target to component
992-
and demote the preview1 stdout path to a named legacy target.
991+
- S6a (WIT export lifting, DONE): codegen emits a `_start : () -> ()`
992+
shim that calls `main` and drops its i32 result whenever a
993+
parameter-less `fn main()` is present (`lib/codegen.ml`);
994+
`tools/componentize.sh --command` wraps with the fetch-pinned
995+
preview1->preview2 *command* adapter (wasmtime v44.0.1, sha256
996+
8ff2ea78...) producing a component that exports `wasi:cli/run@0.2.x`
997+
per `wit/affinescript.wit`. End-to-end gate:
998+
`tests/componentize/command_smoke.sh` proves `wasmtime run` invokes
999+
the component (exit 0), the ownership section survives, and the
1000+
lift is asserted. Purely additive: reactor consumers + game-loop
1001+
hooks are byte-unchanged.
1002+
- S6b: `wasi:sockets`.
1003+
- S6c: flip the default wasm target to component and demote the
1004+
preview1 stdout path to a named legacy target.
9931005
"""
9941006
consequences = """
9951007
- End-state is one-way (the component model becomes the canonical wasm
@@ -1058,23 +1070,34 @@ Thread per-call-site effect rows from typecheck to codegen via a
10581070
`let`-RHS call's effect row ⊇ `Async`” via a table lookup, replacing
10591071
`is_async_prim_call`/`async_primitives`.
10601072
- *Fallback / safety.* If the table has no entry for a site (e.g. a
1061-
pre-typecheck embedder path, or a synthesised node), codegen falls
1062-
back to the structural recogniser. The hardcoded set is retired only
1063-
once the table path is proven (final slice); over-conservative
1064-
fallback is always sound (= today's behaviour).
1073+
pre-typecheck embedder path, or a synthesised node), or the consumer
1074+
detects a producer/consumer count-mismatch, [Effect_sites.is_async_call]
1075+
returns false ⇒ the CPS transform simply does not fire for that call.
1076+
The pre-S4 plan retained the structural recogniser as the fallback
1077+
*until the table path was proven*; S4 (PR #278) retired the
1078+
hardcoded `async_primitives` set, so the steady-state fallback is
1079+
"no transform" — over-conservative, always sound.
10651080

10661081
Staged (ledger #234; each a gated PR, full `dune test --force` +
10671082
wasm e2e):
1068-
- S1 (this): ADR-016 + plan. No code change.
1069-
- S2: `lib/effect_sites.ml` shared numbering + typecheck builds &
1070-
returns the side-table. NO codegen behaviour change (table built,
1071-
unused) — pure, gate-neutral.
1072-
- S3: pipeline threads the table; codegen boundary predicate switches
1073-
to the table with structural fallback; new e2e proving a
1074-
*user-defined* `Async` fn triggers the transform (the payoff). All
1075-
existing http_cps_* / http_response_reader stay green.
1076-
- S4: retire the hardcoded `async_primitives` set (fallback remains
1077-
for table-miss only); doc truthing.
1083+
- S1 (ADR-016 + plan, PR #270): DONE — no code change.
1084+
- S2a (`lib/effect_sites.ml` shared numbering, PR #275): DONE — pure,
1085+
gate-neutral.
1086+
- S2b (typecheck builds & returns the side-table, PR #276): DONE — no
1087+
codegen behaviour change yet.
1088+
- S3 (pipeline threads the table; codegen boundary predicate switches
1089+
to the table with structural fallback; new e2e
1090+
`tests/codegen/effect_async_boundary.affine` proving a *user-defined*
1091+
`Async` fn triggers the transform — PR #277): DONE. All existing
1092+
http_cps_* / http_response_reader stay green.
1093+
- S4 (retire the hardcoded `async_primitives` set; boundary is now
1094+
exactly `Effect_sites.is_async_call`; fallback remains for table-
1095+
empty / count-mismatch only — PR #278): DONE.
1096+
1097+
*Delivery status:* CLOSED 2026-05-19 end-to-end. Issue #234 closed
1098+
completed (`hyperpolymath/affinescript#234`). The structural name set
1099+
no longer exists; the boundary is single-sourced from the typecheck
1100+
effect side-table via the shared `Effect_sites` ordinal.
10781101
"""
10791102
consequences = """
10801103
- Generalises to user-defined `Async` functions; new async primitives

.machine_readable/6a2/STATE.a2ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ test-files = 54
7171
# the feature is not enforced on user programs through the CLI pipeline.
7272
affine-types = "wired-and-reachable (Track A Manhattan plan complete 2026-04-10. Quantity semiring in lib/quantity.ml; invoked from typecheck.ml:1206 inside the standard CLI pipeline. Surface syntax per ADR-007 hybrid: @linear/@erased/@unrestricted attributes (Option C primary) on let/stmt-let/param/lambda-param, AND :1/:0/:ω numeric sugar (Option B) on let/stmt-let. Scaled Let rule per ADR-002 implemented in lib/quantity.ml ExprLet/StmtLet — closes BUG-001 (ω-let smuggles linear values) and BUG-002 (zero-let erasure). Four regression fixtures in test/e2e/fixtures/ exercise both surface forms. Behavioural enforcement verified via E2E Quantity test suite — 4 new passing tests, 0 regressions.)"
7373
linear-arrows = "enforced (2026-04-11): Three-part fix landed. (1) typecheck.ml lambda synth: |@linear x: T| e now synthesises T -[1]-> U (was always QOmega). (2) typecheck.ml lambda check mode: explicit param quantity annotation validated against expected TArrow quantity; unannotated params inherit context quantity. (3) quantity.ml ExprLambda: added env.errors accumulator; annotated lambda params declared via env_declare so env_use tracks them; usage verified with check_quantity after body walk; violations pushed to env.errors and drained at end of check_function_quantities (step 4). Saved/restored env.quantities entries to prevent scope leakage. Two E2E fixtures + 2 passing tests. 75 tests total, 0 regressions. Commit d2f9b7b pushed."
74-
borrow-checker = "phase-3-part-1-landed (CORE-01, PR #240 Refs #177, 2026-05-19, gate 263/263): borrow-graph validation wired — BorrowOutlivesOwner emitted (&local escaping its block), shared-XOR-exclusive enforced at use sites (UseWhileExclusivelyBorrowed), ownership derived from param type TyOwn/TyRef/TyMut (owned/ref/mut discipline now enforced from real parsed source — closed a latent hole), call-arg borrows temporary, ref-binding graph tracked. Part 2+ deferred: NLL/region inference, flow-sensitive escape via `outer = &x`, tighter quantity integration. Authoritative: docs/CAPABILITY-MATRIX.adoc + docs/TECH-DEBT.adoc CORE-01."
74+
borrow-checker = "phase-3-part-3-slice-A-landed (CORE-01, Refs #177, 2026-05-24): pt1 (#240, gate 263/263) borrow-graph validation wired — BorrowOutlivesOwner emitted (&local escaping its block), shared-XOR-exclusive enforced at use sites (UseWhileExclusivelyBorrowed), ownership derived from param type TyOwn/TyRef/TyMut (owned/ref/mut discipline now enforced from real parsed source — closed a latent hole), call-arg borrows temporary, ref-binding graph tracked. pt2 (gate 271→274 and 278→281) return-escape (return-of-ref-rooted-at-callee-owned-binding caught) + &mut e parser surface (zero Menhir conflict delta — exclusive borrow finally expressible from real source). pt3 Slice A NLL last-use expiry: forward pre-pass compute_last_use_index maps each symbol to its greatest mentioning statement index; check_block expires ref-bindings introduced in-block once their binder is dead, releasing the underlying borrow. Unblocks `let r = &x; print(*r); x = 2` and `let m = &mut x; let y = *m; x` while still rejecting same-block live aliasing (2 positive + 1 anti-regression hermetic tests in E2E Borrow Graph). Residual (Slices B–D): flow-sensitive escape via `outer = &x`, origin/region variables (Polonius surface) + loan-live-at-point dataflow across CFG joins, tighter quantity integration. Authoritative: docs/CAPABILITY-MATRIX.adoc + docs/TECH-DEBT.adoc CORE-01."
7575
row-polymorphism = "60% (records + effects rows implemented in typecheck/unify; not fully exercised end-to-end)"
7676
effects = "interpreter-complete (handler dispatch, PerformEffect propagation, ExprResume, multi-arg ops all wired in interp.ml 2026-04-11). WasmGC: ops registered as unreachable stubs; ExprHandle/ExprResume reject with UnsupportedFeature — full WASM dispatch needs EH proposal or CPS transform."
7777
dependent-types = "parse-only (TRefined AST node exists and refinement predicates parse, but predicates do not reduce; no SMT/decision procedure wired in)"

0 commit comments

Comments
 (0)