Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ for the canonical statement.

| Language/Tool | Use Case | Notes |
|---------------|----------|-------|
| **ReScript** | Primary application code | Compiles to JS, type-safe |
| **AffineScript** | Primary application code | Compiles to typed-wasm; affine/linear types. Replaces ReScript across the estate (RS/TS/JS → AffineScript → typed-wasm). |
| **Deno** | Runtime & package management | Replaces Node/npm/bun |
| **Rust/SPARK** | Performance-critical, systems, WASM, CLI tools, safety-critical | "Rust" always means "Rust/SPARK" per terminology note above. Preferred over Ada where reachable. |
| **Zig** | FFI layer (hyperpolymath ABI/FFI standard), memory-safe systems where Rust/SPARK is overkill | Also the migration target for V-lang |
Expand All @@ -43,7 +43,7 @@ for the canonical statement.
| **Elixir** | Backend services, distributed systems | BEAM, Phoenix, OTP |
| **Haskell** | Type-heavy tools, registry validation | Scaffoldia CLI |
| **Bash/POSIX Shell** | Scripts, automation | Keep minimal |
| **JavaScript** | Only where ReScript cannot | MCP protocol glue, Deno APIs |
| **JavaScript** | Only where AffineScript cannot | MCP protocol glue, Deno APIs (transitional; prefer .affine where possible) |
| **Nickel** | Configuration language | For complex configs |
| **A2ML** | State/meta files | STATE.a2ml, META.a2ml, etc. (TOML-like format) |
| **Julia** | Batch scripts, data processing | Per RSR |
Expand All @@ -54,13 +54,14 @@ for the canonical statement.

| Banned | Replacement | Notes |
|--------|-------------|-------|
| TypeScript | ReScript | |
| TypeScript | AffineScript | RS/TS/JS → AffineScript → typed-wasm. |
| **ReScript** | AffineScript | Banned in new code as of 2026-04-30. Existing `.res` files migrate to `.affine` directly (do not pass through ReScript). |
| Node.js | Deno | |
| npm | Deno | |
| Bun | Deno | |
| pnpm/yarn | Deno | |
| Go | Rust/SPARK | |
| **Python** | ReScript/Rust/SPARK/Julia | Fully banned, no exceptions (SaltStack exception removed 2026-01-03) |
| **Python** | AffineScript/Rust/SPARK/Julia | Fully banned, no exceptions (SaltStack exception removed 2026-01-03) |
| Java/Kotlin | Rust/SPARK, Tauri, Dioxus | |
| Swift | Tauri/Dioxus | |
| React Native | Tauri/Dioxus | |
Expand All @@ -70,7 +71,8 @@ for the canonical statement.
| **Makefiles** | Mustfile/justfile | |

**NOTE:** Python is fully banned. V-lang is fully banned (2026-04-10). ATS2 is
fully banned in favour of Idris2 + Rust/SPARK. All three bans are enforced by
fully banned in favour of Idris2 + Rust/SPARK. ReScript is fully banned in new
code as of 2026-04-30 (use AffineScript). All four bans are enforced by
`.github/workflows/language-policy.yml`.

### Build System
Expand All @@ -87,14 +89,14 @@ See: https://github.com/hyperpolymath/mustfile

**No exceptions for Kotlin/Swift** - use Rust-first approach:

1. **Tauri 2.0+** - Web UI (ReScript) + Rust backend, MIT/Apache-2.0
1. **Tauri 2.0+** - Web UI (AffineScript → typed-wasm) + Rust backend, MIT/Apache-2.0
2. **Dioxus** - Pure Rust native UI, MIT/Apache-2.0

Both are FOSS with independent governance (no Big Tech).

### Enforcement Rules

1. **No new TypeScript files** - Convert existing TS to ReScript
1. **No new TypeScript or ReScript files** - Convert existing TS/RS to AffineScript directly (`.affine`); ReScript is no longer the destination
2. **No package.json for runtime deps** - Use deno.json imports
3. **No node_modules in production** - Deno caches deps automatically
4. **No Go code** - Use Rust instead
Expand Down
26 changes: 19 additions & 7 deletions .github/workflows/language-policy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,23 @@ jobs:
- name: Check for TypeScript files
run: |
if find . -name "*.ts" -o -name "*.tsx" | grep -v node_modules | grep -v ".d.ts" | head -1 | grep -q .; then
echo "::error::TypeScript files found. Use ReScript instead."
echo "::error::TypeScript files found. Use AffineScript instead."
find . -name "*.ts" -o -name "*.tsx" | grep -v node_modules | grep -v ".d.ts"
exit 1
fi
echo "✓ No TypeScript files found"

- name: Check for ReScript files
run: |
# Estate policy: RS/TS/JS -> AffineScript -> typed-wasm.
# ReScript (.res) is no longer the TS replacement.
if find . -name "*.res" | grep -v node_modules | head -1 | grep -q .; then
echo "::error::ReScript files found. Use AffineScript instead."
find . -name "*.res" | grep -v node_modules
exit 1
fi
echo "✓ No ReScript files found"

- name: Check for Go files
run: |
if find . -name "*.go" | head -1 | grep -q .; then
Expand All @@ -41,7 +52,7 @@ jobs:
# Allow Python only in ansible/ directories or for Ansible-specific files
PYTHON_FILES=$(find . -name "*.py" | grep -v __pycache__ | grep -v ".venv" | grep -v "ansible" | grep -v "molecule" || true)
if [ -n "$PYTHON_FILES" ]; then
echo "::error::Python files found outside Ansible context. Rewrite in Rust/ReScript."
echo "::error::Python files found outside Ansible context. Rewrite in Rust/AffineScript."
echo "$PYTHON_FILES"
exit 1
fi
Expand Down Expand Up @@ -139,11 +150,12 @@ jobs:
echo "::warning::.machine_readable/ directory not found"
else
echo "✓ .machine_readable/ directory exists"
for scm in STATE META ECOSYSTEM AGENTIC NEUROSYM PLAYBOOK; do
if [ ! -f ".machine_readable/${scm}.scm" ]; then
echo "::warning::Missing .machine_readable/${scm}.scm"
# Per estate policy: .a2ml is canonical; .scm is reserved for Guix.
for a2ml in STATE META ECOSYSTEM AGENTIC NEUROSYM PLAYBOOK; do
if [ ! -f ".machine_readable/6a2/${a2ml}.a2ml" ] && [ ! -f ".machine_readable/${a2ml}.a2ml" ]; then
echo "::warning::Missing .machine_readable/6a2/${a2ml}.a2ml (or top-level fallback)"
else
echo "✓ .machine_readable/${scm}.scm exists"
echo "✓ ${a2ml}.a2ml present"
fi
done
fi
Expand All @@ -159,7 +171,7 @@ jobs:
- name: Check SPDX headers
run: |
MISSING_SPDX=0
for ext in rs res js jsx mjs ts tsx py go java kt swift sh bash; do
for ext in rs affine js jsx mjs ts tsx py go java kt swift sh bash; do
while IFS= read -r file; do
if [ -n "$file" ] && ! head -5 "$file" | grep -q "SPDX-License-Identifier"; then
echo "::warning::Missing SPDX header: $file"
Expand Down
35 changes: 27 additions & 8 deletions .github/workflows/rsr-antipattern.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# SPDX-License-Identifier: PMPL-1.0
# RSR Anti-Pattern CI Check
# SPDX-License-Identifier: PMPL-1.0
#
# Enforces: No TypeScript, No Go, No Python (except SaltStack), No npm
# Allows: ReScript, Deno, WASM, Rust, OCaml, Haskell, Guile/Scheme
# Enforces: No TypeScript, No ReScript, No Go, No Python (except SaltStack), No npm
# Allows: AffineScript, Deno, WASM, Rust, OCaml, Haskell, Guile/Scheme

name: RSR Anti-Pattern Check

Expand All @@ -28,15 +27,27 @@ jobs:
- name: Check for TypeScript
run: |
# Exclude bindings/deno/ - those are Deno FFI files using Deno.dlopen, not plain TypeScript
# Exclude .d.ts files - those are TypeScript type declarations for ReScript FFI
# Exclude .d.ts files - generated type declarations for FFI
TS_FILES=$(find . \( -name "*.ts" -o -name "*.tsx" \) | grep -v node_modules | grep -v 'bindings/deno' | grep -v '\.d\.ts$' || true)
if [ -n "$TS_FILES" ]; then
echo "❌ TypeScript files detected - use ReScript instead"
echo "❌ TypeScript files detected - use AffineScript instead"
echo "$TS_FILES"
exit 1
fi
echo "✅ No TypeScript files (Deno FFI bindings excluded)"

- name: Check for ReScript
run: |
# Estate policy: RS/TS/JS -> AffineScript -> typed-wasm. ReScript (.res)
# is no longer used as the TS replacement; new code uses .affine instead.
RES_FILES=$(find . -name "*.res" | grep -v node_modules || true)
if [ -n "$RES_FILES" ]; then
echo "❌ ReScript files detected - use AffineScript instead"
echo "$RES_FILES"
exit 1
fi
echo "✅ No ReScript files"

- name: Check for Go
run: |
if find . -name "*.go" | grep -q .; then
Expand Down Expand Up @@ -67,11 +78,19 @@ jobs:
- name: Check for tsconfig
run: |
if [ -f "tsconfig.json" ]; then
echo "❌ tsconfig.json detected - use ReScript instead"
echo "❌ tsconfig.json detected - use AffineScript instead"
exit 1
fi
echo "✅ No tsconfig.json"

- name: Check for rescript.json
run: |
if [ -f "rescript.json" ] || [ -f "bsconfig.json" ]; then
echo "❌ rescript.json/bsconfig.json detected - use AffineScript config instead"
exit 1
fi
echo "✅ No rescript.json/bsconfig.json"

- name: Verify Deno presence (if package.json exists)
run: |
if [ -f "package.json" ]; then
Expand All @@ -86,8 +105,8 @@ jobs:
echo "╔════════════════════════════════════════════════════════════╗"
echo "║ RSR Anti-Pattern Check Passed ✅ ║"
echo "║ ║"
echo "║ Allowed: ReScript, Deno, WASM, Rust, OCaml, Haskell, ║"
echo "║ Allowed: AffineScript, Deno, WASM, Rust, OCaml, Haskell, ║"
echo "║ Guile/Scheme, SaltStack (Python) ║"
echo "║ ║"
echo "║ Blocked: TypeScript, Go, npm, Python (non-Salt) ║"
echo "║ Blocked: TypeScript, ReScript, Go, npm, Python (non-Salt)║"
echo "╚════════════════════════════════════════════════════════════╝"
23 changes: 14 additions & 9 deletions .github/workflows/ts-blocker.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: PMPL-1.0-or-later
name: TypeScript/JavaScript Blocker
name: TypeScript / JavaScript / ReScript Blocker
on: [push, pull_request]

permissions:
Expand All @@ -12,15 +12,20 @@ jobs:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Block new TypeScript/JavaScript
- name: Block new TypeScript / JavaScript / ReScript
run: |
# Estate language policy: RS/TS/JS -> AffineScript -> typed-wasm.
# ReScript (.res) is also banned now that AffineScript is the destination
# — no longer used as the TS replacement.
NEW_TS=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E '\.(ts|tsx)$' | grep -v '\.gen\.' || true)
NEW_JS=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E '\.(js|jsx)$' | grep -v '\.res\.js$' | grep -v '\.gen\.' | grep -v 'node_modules' || true)

if [ -n "$NEW_TS" ] || [ -n "$NEW_JS" ]; then
echo "❌ New TS/JS files detected. Use ReScript instead."
[ -n "$NEW_TS" ] && echo "$NEW_TS"
[ -n "$NEW_JS" ] && echo "$NEW_JS"
NEW_JS=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E '\.(js|jsx)$' | grep -v '\.gen\.' | grep -v 'node_modules' || true)
NEW_RES=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E '\.res$' || true)

if [ -n "$NEW_TS" ] || [ -n "$NEW_JS" ] || [ -n "$NEW_RES" ]; then
echo "❌ New TS/JS/ReScript files detected. Use AffineScript instead."
[ -n "$NEW_TS" ] && echo "$NEW_TS"
[ -n "$NEW_JS" ] && echo "$NEW_JS"
[ -n "$NEW_RES" ] && echo "$NEW_RES"
exit 1
fi
echo "✅ ReScript policy enforced"
echo "✅ AffineScript policy enforced"
19 changes: 12 additions & 7 deletions .machine_readable/contractiles/must/Mustfile.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ These are hard requirements — CI and pre-commit hooks fail if any check fails.

## Web Client

### rescript-json-present
- description: ReScript config exists for web client
- run: test -f client/web/rescript.json
### affinescript-config-present
- description: AffineScript config exists for web client (replaces former rescript-json-present)
- run: test -f client/web/affinescript.toml || test -f client/web/dune-project
- severity: warning

### web-entry-point
Expand Down Expand Up @@ -98,8 +98,8 @@ These are hard requirements — CI and pre-commit hooks fail if any check fails.
- severity: critical

### no-unsafe-coerce
- description: No unsafeCoerce in ReScript/Haskell code
- run: test -z "$(find . \( -name '*.res' -o -name '*.hs' \) -not -path '*/deps/*' -not -path '*/node_modules/*' -exec grep -l 'unsafeCoerce\|Obj.magic' {} \; 2>/dev/null)"
- description: No unsafeCoerce / Obj.magic in source (legacy ReScript/Haskell patterns; AffineScript has no equivalent escape hatch by design)
- run: test -z "$(find . \( -name '*.affine' -o -name '*.hs' \) -not -path '*/deps/*' -not -path '*/node_modules/*' -exec grep -l 'unsafeCoerce\|Obj.magic' {} \; 2>/dev/null)"
- severity: critical

## Container Policy
Expand All @@ -117,12 +117,17 @@ These are hard requirements — CI and pre-commit hooks fail if any check fails.
## Language Policy

### no-typescript
- description: No TypeScript files (use ReScript)
- description: No TypeScript files (use AffineScript)
- run: test -z "$(find . -name '*.ts' -not -name '*.d.ts' -not -path '*/deps/*' -not -path '*/node_modules/*' 2>/dev/null)"
- severity: warning

### no-rescript
- description: No ReScript files (use AffineScript)
- run: test -z "$(find . -name '*.res' -not -path '*/deps/*' -not -path '*/node_modules/*' 2>/dev/null)"
- severity: warning

### no-python
- description: No Python files (use Julia/Rust/ReScript)
- description: No Python files (use Julia/Rust/AffineScript)
- run: test -z "$(find . -name '*.py' -not -path '*/deps/*' -not -path '*/node_modules/*' 2>/dev/null)"
- severity: warning

Expand Down
4 changes: 2 additions & 2 deletions 0-ai-gatekeeper-protocol/RSR_OUTLINE.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ project/

=== Language Tiers

* **Tier 1** (Gold): Rust, Elixir, Zig, Ada, Haskell, ReScript
* **Tier 1** (Gold): Rust(+SPARK), Elixir, Zig, Ada, Haskell, AffineScript
* **Tier 2** (Silver): Nickel, Racket, Guile Scheme, Nix
* **Infrastructure**: Guix channels, derivations

Expand All @@ -166,7 +166,7 @@ project/
=== Prohibited

* Python outside `salt/` directory
* TypeScript/JavaScript (use ReScript)
* TypeScript/JavaScript/ReScript (use AffineScript)
* CUE (use Guile/Nickel)
* `Dockerfile` (use `Containerfile`)

Expand Down
4 changes: 2 additions & 2 deletions 0-ai-gatekeeper-protocol/repo-guardian-fs/RSR_OUTLINE.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ project/

=== Language Tiers

* **Tier 1** (Gold): Rust, Elixir, Zig, Ada, Haskell, ReScript
* **Tier 1** (Gold): Rust(+SPARK), Elixir, Zig, Ada, Haskell, AffineScript
* **Tier 2** (Silver): Nickel, Racket, Guile Scheme, Nix
* **Infrastructure**: Guix channels, derivations

Expand All @@ -166,7 +166,7 @@ project/
=== Prohibited

* Python outside `salt/` directory
* TypeScript/JavaScript (use ReScript)
* TypeScript/JavaScript/ReScript (use AffineScript)
* CUE (use Guile/Nickel)
* `Dockerfile` (use `Containerfile`)

Expand Down
4 changes: 2 additions & 2 deletions a2ml-templates/AGENTIC.a2ml.template
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ documentation = "inline"
# ── Language Constraints ──────────────────────────────────────────────────
[agentic-config.constraints]
# languages: Languages the agent is allowed to write in this project.
languages = ["rescript", "rust", "gleam", "{{PRIMARY_LANGUAGE}}"]
languages = ["affinescript", "rust", "gleam", "{{PRIMARY_LANGUAGE}}"]

# banned: Languages the agent must NEVER use, even if asked.
banned = ["typescript", "go", "python", "makefile"]
banned = ["typescript", "rescript", "go", "python", "makefile"]

# ── Project-Specific Overrides ────────────────────────────────────────────
[agentic-config.project-specific]
Expand Down
2 changes: 1 addition & 1 deletion a2ml-templates/META.a2ml.template
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ name = "{{PROJECT_NAME}}"
# ── Development Practices ──────────────────────────────────────────────────
[project-meta.development-practices]
# code-style: Which language's conventions to follow.
# Common values: rescript, rust, gleam, elixir, idris2
# Common values: affinescript, rust, gleam, elixir, idris2
code-style = "{{CODE_STYLE}}"

# security: Which security framework is used.
Expand Down
Loading
Loading