From 05a785ed4650b9da418edec0dc4468225da0c2e5 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Jun 2026 09:02:20 +0000 Subject: [PATCH 1/4] chore: add root Mustfile (RSR-mandatory checks contract) Adds the root Mustfile required by REQUIRED-FILES.adoc (was missing across the -iser family). Declares the mandatory checks, each mapping to an existing Justfile recipe (just lint / test / fmt). Part of the base-camp RSR compliance sweep. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Mbq6yKF9RhFai6EQ7WqKhQ --- Mustfile | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Mustfile diff --git a/Mustfile b/Mustfile new file mode 100644 index 0000000..a864992 --- /dev/null +++ b/Mustfile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: MPL-2.0 +# Mustfile — hyperpolymath mandatory checks +# See: https://github.com/hyperpolymath/mustfile +# +# Declarative contract of checks that MUST pass. Each maps to a recipe +# that already exists in this repo's Justfile. +version: 1 + +checks: + - name: security + run: just lint + - name: tests + run: just test + - name: format + run: just fmt From 521fb3a2bd4e9864f4b15a4502d813bb23d3bd17 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Jun 2026 09:06:28 +0000 Subject: [PATCH 2/4] =?UTF-8?q?chore:=20port=20examples/SafeDOMExample.res?= =?UTF-8?q?=20=E2=86=92=20.affine=20(banned-ReScript=20removal)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the banned ReScript example with the canonical estate-wide AffineScript port (gitbot-fleet#208 sweep; identical to otpiser). Clears the `governance / Language / package anti-pattern policy` gate (cicd_rules/banned_language_file), which hard-fails on any tracked *.res. Documented resolution per the k9iser HANDOFF (port → AffineScript). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Mbq6yKF9RhFai6EQ7WqKhQ --- examples/SafeDOMExample.affine | 129 +++++++++++++++++++++++++++++++++ examples/SafeDOMExample.res | 109 ---------------------------- 2 files changed, 129 insertions(+), 109 deletions(-) create mode 100644 examples/SafeDOMExample.affine delete mode 100644 examples/SafeDOMExample.res diff --git a/examples/SafeDOMExample.affine b/examples/SafeDOMExample.affine new file mode 100644 index 0000000..2a62c1d --- /dev/null +++ b/examples/SafeDOMExample.affine @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: MPL-2.0 +// SafeDOMExample.affine — formally-verified DOM mounting (aspirational). +// +// This example shows the *shape* of SafeDOM consumer code in current +// AffineScript syntax. The `SafeDOM` stdlib surface it references +// (`mount_safe`, `mount_when_ready`, `mount_batch`, +// `proven_selector_validate`, `proven_html_validate`, `mount`) is the +// target of `affinescript#56` (DOM+Pixi binding survey) and does not +// yet exist in the published stdlib. The file is therefore +// parse-checked but not type-checked end-to-end until #56 lands the +// bindings; `affinescript check` reports `Resolve.UndefinedModule +// SafeDOM` which is expected. +// +// Previous versions of this file (estate-wide, 5 dialect variants) +// pre-dated ADR-014 (qualified paths), ADR-016 (effect rows), and the +// `#{`-record-literal sigil (ADR-215). They were retired in favour of +// this canonical via the gitbot-fleet#208 sweep (2026-05-26). + +module SafeDOMExample; + +use prelude::{Option, Some, None, Result, Ok, Err}; + +// `Element` and friends are nominal extern types for now — the real +// shape lands with affinescript#56. +extern type Element; +extern type Selector; +extern type ValidHTML; + +// Single-mount status, lifted from the host into a typed tag union. +enum MountStatus { + Mounted(Element), + MountPointNotFound(String), + InvalidSelector(String), + InvalidHTML(String) +} + +// Batch-mount result. +enum MountResult { + Mounted([Element]), + Failed(String) +} + +// Spec for one element in a batch mount. +struct MountSpec { + selector: String, + html: String +} + +// SafeDOM's host-side surface, all IO-effecting. Callbacks are passed +// as separate parameters (rather than a `MountCallbacks` record) +// because fn-typed struct fields are not currently parser-supported. +extern fn mount_safe( + selector: ref String, + html: ref String, + on_success: fn(Element) -> (), + on_error: fn(String) -> (), +) -{IO}-> (); + +extern fn mount_when_ready( + selector: ref String, + html: ref String, + on_success: fn(Element) -> (), + on_error: fn(String) -> (), +) -{IO}-> (); + +extern fn mount_batch(specs: ref [MountSpec]) -{IO}-> MountResult; + +extern fn proven_selector_validate(s: ref String) -{IO}-> Result; +extern fn proven_html_validate(s: ref String) -{IO}-> Result; +extern fn mount(sel: ref Selector, html: ref ValidHTML) -{IO}-> MountStatus; + +extern fn array_for_each(xs: ref [Element], f: fn(Element) -> ()) -{IO}-> (); +extern fn array_len(xs: ref [Element]) -> Int; + +// Example 1 — basic mount with success/error branches. +pub fn mount_app() -{IO}-> () { + mount_safe( + "#app", + "

Hello, World!

Mounted safely with proofs.

", + fn(el) -> () { Console::log("App mounted successfully"); }, + fn(err) -> () { Console::error("Mount failed: " ++ err); }, + ); +} + +// Example 2 — defer until DOM ready. +pub fn mount_when_dom_ready() -{IO}-> () { + mount_when_ready( + "#app", + "

App Title

", + fn(_el) -> () { Console::log("Mounted after DOM ready"); }, + fn(err) -> () { Console::error("Failed: " ++ err); }, + ); +} + +// Example 3 — atomic batch mount. +pub fn mount_multiple() -{IO}-> () { + let specs = [ + MountSpec #{ selector: "#header", html: "

Site Title

" }, + MountSpec #{ selector: "#nav", html: "" }, + MountSpec #{ selector: "#main", html: "

Content here

" }, + MountSpec #{ selector: "#footer", html: "
2026
" }, + ]; + + match mount_batch(specs) { + Mounted(elements) => { + Console::log("Batch mount succeeded"); + array_for_each(elements, fn(_el) -> () { Console::log(" element"); }); + }, + Failed(err) => { + Console::error("Batch mount failed (atomic — none mounted): " ++ err); + } + } +} + +// Example 4 — explicit two-stage validation before mounting. +pub fn mount_with_validation() -{IO}-> () { + match proven_selector_validate("#my-app") { + Err(e) => Console::error("Invalid selector: " ++ e), + Ok(valid_selector) => match proven_html_validate("
Content
") { + Err(e) => Console::error("Invalid HTML: " ++ e), + Ok(valid_html) => match mount(valid_selector, valid_html) { + Mounted(_el) => Console::log("Mounted with validated inputs"), + MountPointNotFound(s) => Console::error("Element not found: " ++ s), + InvalidSelector(_) => Console::error("impossible — already validated"), + InvalidHTML(_) => Console::error("impossible — already validated"), + }, + }, + } +} diff --git a/examples/SafeDOMExample.res b/examples/SafeDOMExample.res deleted file mode 100644 index e5c9046..0000000 --- a/examples/SafeDOMExample.res +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -// Example: Using SafeDOM for formally verified DOM mounting - -open SafeDOM - -// Example 1: Basic mounting with error handling -let mountApp = () => { - mountSafe( - "#app", - "

Hello, World!

Mounted safely with proofs.

", - ~onSuccess=el => { - Console.log("✓ App mounted successfully!") - Console.log("Element:", el) - }, - ~onError=err => { - Console.error("✗ Mount failed:", err) - } - ) -} - -// Example 2: Wait for DOM ready before mounting -let mountWhenDOMReady = () => { - mountWhenReady( - "#app", - "

App Title

", - ~onSuccess=_ => Console.log("✓ Mounted after DOM ready"), - ~onError=err => Console.error("✗ Failed:", err) - ) -} - -// Example 3: Batch mounting (atomic - all or nothing) -let mountMultiple = () => { - let specs = [ - {selector: "#header", html: "

Site Title

"}, - {selector: "#nav", html: ""}, - {selector: "#main", html: "

Content here

"}, - {selector: "#footer", html: "
© 2026
"} - ] - - switch mountBatch(specs) { - | Ok(elements) => { - Console.log(`✓ Successfully mounted ${Array.length(elements)} elements`) - elements->Array.forEach(el => Console.log(" -", el)) - } - | Error(err) => { - Console.error("✗ Batch mount failed:", err) - Console.error(" (None were mounted - atomic operation)") - } - } -} - -// Example 4: Explicit validation before mounting -let mountWithValidation = () => { - // Validate selector first - switch ProvenSelector.validate("#my-app") { - | Error(e) => Console.error(`Invalid selector: ${e}`) - | Ok(validSelector) => { - // Validate HTML - switch ProvenHTML.validate("
Content
") { - | Error(e) => Console.error(`Invalid HTML: ${e}`) - | Ok(validHtml) => { - // Now mount with proven safety - switch mount(validSelector, validHtml) { - | Mounted(el) => Console.log("✓ Mounted with validated inputs:", el) - | MountPointNotFound(s) => Console.error(`✗ Element not found: ${s}`) - | InvalidSelector(_) => Console.error("Impossible - already validated") - | InvalidHTML(_) => Console.error("Impossible - already validated") - } - } - } - } -} - -// Example 5: Integration with TEA -module MyApp = { - type model = {message: string} - type msg = NoOp - - let init = () => {message: "Hello from TEA"} - let update = (model, _msg) => model - let view = model => `

${model.message}

` -} - -let mountTEAApp = () => { - let model = MyApp.init() - let html = MyApp.view(model) - - mountWhenReady( - "#tea-app", - html, - ~onSuccess=el => { - Console.log("✓ TEA app mounted") - // Set up event handlers, subscriptions here - }, - ~onError=err => Console.error(`✗ TEA mount failed: ${err}`) - ) -} - -// Entry point -let main = () => { - Console.log("SafeDOM Examples") - Console.log("================\n") - - // Choose which example to run - mountWhenDOMReady() // Run on DOM ready -} - -// Auto-execute when module loads -main() From 112bd98a9c2f26e1867af85b2ec06b803d98a483 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Jun 2026 09:11:05 +0000 Subject: [PATCH 3/4] ci: switch CodeQL matrix javascript-typescript -> actions (Hypatia-prescribed) The repo has no JS/TS source, so `analyze (javascript-typescript, none)` failed on every run with "no source files". Switch the CodeQL matrix to `actions` (scans the GitHub Actions workflows every repo has), per Hypatia's `switch_codeql_matrix_to_actions` recommendation. build-mode none is correct for the actions language. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Mbq6yKF9RhFai6EQ7WqKhQ --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9e32d15..0395eea 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -30,7 +30,7 @@ jobs: fail-fast: false matrix: include: - - language: javascript-typescript + - language: actions build-mode: none steps: From e817b7d947677d97ca469593eab1766b49bd2ae9 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Jun 2026 10:30:07 +0000 Subject: [PATCH 4/4] docs: de-dup CHANGELOG/README per RSR standard (keep .adoc; port sponsor badge) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keeps the maintained CHANGELOG.adoc, removes the stale v0.1.0 CHANGELOG.md stub (verisimiser reversed — its .md is the richer/canonical one). Removes the duplicate README.md, porting its sponsor badge into README.adoc so the rendered GitHub page keeps it. RSR: no duplicate doc formats. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Mbq6yKF9RhFai6EQ7WqKhQ --- CHANGELOG.md | 18 ------ README.adoc | 2 + README.md | 165 --------------------------------------------------- 3 files changed, 2 insertions(+), 183 deletions(-) delete mode 100644 CHANGELOG.md delete mode 100644 README.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index aea918b..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,18 +0,0 @@ -# Changelog - -All notable changes to chapeliser will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [0.1.0] - 2026-03-20 - -### Added -- Initial project scaffold from rsr-template-repo -- CLI with subcommands (init, validate, generate, build, run, info) -- Manifest parser (`chapeliser.toml`) -- Codegen engine (stubs — target-language-specific implementation pending) -- ABI module (Idris2 proof type definitions) -- Library API for programmatic use -- Full RSR template (17 CI workflows, governance docs, bot directives) -- README.adoc with architecture overview and value proposition diff --git a/README.adoc b/README.adoc index c9aef9f..1175893 100644 --- a/README.adoc +++ b/README.adoc @@ -7,6 +7,8 @@ Jonathan D.A. Jewell :icons: font :source-highlighter: rouge +image:https://img.shields.io/badge/Sponsor-%E2%9D%A4-pink?logo=github[Sponsor,link=https://github.com/sponsors/hyperpolymath] + == What Is This? Chapeliser is a **general-purpose Chapel acceleration framework** that lets diff --git a/README.md b/README.md deleted file mode 100644 index 61e2c4a..0000000 --- a/README.md +++ /dev/null @@ -1,165 +0,0 @@ -[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-pink?logo=github)](https://github.com/sponsors/hyperpolymath) - -// SPDX-License-Identifier: MPL-2.0 -// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) -= Chapeliser -Jonathan D.A. Jewell -:toc: left -:toclevels: 3 -:icons: font -:source-highlighter: rouge - -== What Is This? - -Chapeliser is a **general-purpose Chapel acceleration framework** that lets -developers scale single-machine applications to distributed clusters without -learning Chapel. - -You describe your workload in a manifest (`chapeliser.toml`), point Chapeliser -at your code, and it generates the distributed scaffolding — Chapel `coforall` -loops, data partitioning, result gathering, and the ABI/FFI bridge between your -application and the Chapel runtime. - -== The Problem - -Chapel is one of the most powerful parallel programming languages ever built. -It can distribute computation across thousands of nodes with elegant syntax. -But almost nobody uses it because: - -1. **Steep learning curve** — you must rewrite your application in Chapel or - deeply understand its interop model -2. **No incremental adoption path** — it's all-or-nothing -3. **Build system complexity** — integrating Chapel with existing Rust/C/Zig - projects is non-trivial - -Chapeliser solves all three. - -== How It Works - -[source] ----- -Your application (Rust, C, Zig) - │ - ▼ -chapeliser.toml ──► Chapeliser CLI - │ │ - │ ┌───────────┴───────────┐ - │ │ │ - ▼ ▼ ▼ - Idris2 ABI Zig FFI Chapel wrapper - (formal proof of (C-ABI bridge (coforall + data - data layout + to Chapel distribution + - partition safety) runtime) gather/reduce) - │ │ │ - └────────┬───────┘ │ - ▼ │ - generated/abi/*.h ◄───────────────────┘ - │ - ▼ - Your app, now distributed ----- - -=== The Manifest - -[source,toml] ----- -[workload] -name = "my-scanner" -entry = "src/batch.rs::scan_all" # function to distribute -partition = "per-item" # split strategy -gather = "merge" # combine strategy - -[data] -input-type = "Vec" # what gets distributed -output-type = "Vec" # what comes back -serialization = "bincode" # wire format - -[scaling] -min-nodes = 1 # runs locally if alone -max-nodes = 256 # scales to cluster -grain-size = 50 # items per Chapel task ----- - -You write **zero Chapel code**. Chapeliser generates everything. - -=== Partition Strategies - -|=== -| Strategy | Description | Best For - -| `per-item` | One item per task | File scanning, image processing -| `chunk` | Fixed-size chunks | Data pipelines, ETL -| `adaptive` | Dynamic load balancing | Heterogeneous workloads -| `spatial` | Domain decomposition | Simulation, matrices -| `keyed` | Group by key | Map-reduce, aggregation -|=== - -=== Gather Strategies - -|=== -| Strategy | Description - -| `merge` | Concatenate all results -| `reduce` | Apply reduction function (sum, max, min, custom) -| `tree-reduce` | Logarithmic reduction for associative ops -| `stream` | Results stream back as they complete -| `first` | Return first successful result (search) -|=== - -== Architecture - -Chapeliser follows the hyperpolymath ABI-FFI standard: - -* **Idris2 ABI** (`src/abi/`) — Formal proofs that: - - Data layouts are consistent across nodes - - Partition functions produce complete, non-overlapping splits - - Gather functions preserve all results - - Serialization round-trips are identity - -* **Zig FFI** (`ffi/zig/`) — C-ABI bridge between: - - The user's application (any language with C FFI) - - The Chapel runtime (`chpl_*` functions) - - Memory management across the boundary - -* **Chapel codegen** (`src/codegen/`) — Generates: - - `coforall` distribution loops - - Locale-aware data placement - - Communication primitives (GET/PUT/AMO) - - Fault tolerance (retry, checkpoint, redistribute) - -* **Rust CLI** (`src/`) — The `chapeliser` command: - - Parses `chapeliser.toml` - - Validates workload description - - Generates Chapel + Zig + C header scaffolding - - Builds and links everything - - Provides `chapeliser run` for execution - -== Quick Start - -[source,bash] ----- -# Install -cargo install chapeliser - -# In your project directory, create chapeliser.toml (see above) -chapeliser init # generates scaffold from manifest -chapeliser build # compiles Chapel wrapper + FFI bridge -chapeliser run # executes locally (1 node) -chapeliser run -n 8 # distributes across 8 nodes -chapeliser run --cluster my-cluster.toml # full cluster ----- - -== First Consumer: panic-attacker - -The first application to be Chapelised is -https://github.com/hyperpolymath/panic-attacker[panic-attacker]'s -`mass-panic` (assemblyline) mode — distributing static analysis across -hundreds of repositories on a compute cluster. - -== Status - -**Pre-alpha.** Architecture defined, ABI proofs in progress, codegen planned. - -== License - -SPDX-License-Identifier: MPL-2.0