Skip to content

Commit d4b0dc3

Browse files
respencer-nclclaude
andcommitted
Update CLAUDE.md and NOTEBOOK.md for 1.4.0 release
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a79f7a5 commit d4b0dc3

2 files changed

Lines changed: 182 additions & 8 deletions

File tree

CLAUDE.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,29 @@ redirects to ossum.tech. Do not add new documentation here.
2121

2222
RIDDL (Reactive Interface to Domain Definition Language) is a specification language for designing distributed, reactive, cloud-native systems using DDD principles. It's a **monorepo** containing multiple cross-platform Scala modules.
2323

24+
## Backward Compatibility Policy
25+
26+
RIDDL is a heavily used library both by Ossum Inc. and external
27+
consumers. **Never make incompatible changes** to public APIs without
28+
following this process:
29+
30+
1. **No removal of public API** — Do not remove public methods, classes,
31+
traits, or extension methods. If functionality must be retired, add
32+
`@deprecated` annotations with a migration message and the target
33+
major version for removal (e.g., `@deprecated("Use flatten() instead",
34+
"2.0.0")`).
35+
2. **No breaking signature changes** — Do not change parameter types,
36+
return types, or add required parameters to existing public methods.
37+
New parameters must have defaults.
38+
3. **Deprecation warnings until next major release** — Deprecated APIs
39+
must remain functional through the current major version (1.x). They
40+
may only be removed in the next major release (2.0.0).
41+
4. **Additive changes only** — New methods, extension methods, classes,
42+
and traits are always safe. Prefer adding new APIs alongside old ones
43+
rather than modifying existing ones.
44+
45+
When in doubt, **add, don't change**.
46+
2447
## Critical Build Information
2548

2649
### Scala Version & Syntax
@@ -658,3 +681,7 @@ Then add to root aggregation: `.aggregate(..., mymodule, mymoduleJS, mymoduleNat
658681
25. **gh auth needs write:packages for npm** - Run `gh auth refresh -s write:packages` if publishing to GH Packages npm registry
659682
26. **OutlinePass and TreePass** - Lightweight HierarchyPass subclasses in `passes/shared/.../passes/`. OutlinePass produces flat `Seq[OutlineEntry]`; TreePass produces recursive `Seq[TreeNode]`. Exposed via `RiddlAPI.getOutline()` and `RiddlAPI.getTree()` with TypeScript declarations
660683
27. **riddlLibJS test runner crashes are benign** - `RPCCore$ClosedException` in `riddlLibJS/Test` is a Scala.js test adapter teardown issue, not a code failure. The module has no test classes; all actual tests pass
684+
28. **NEVER put `import '`, `import "`, or `import(` in shared string literals** - ESM shim plugins scan the JS bundle and rewrite these patterns. Use string concatenation (`"im" + "port"`) or rephrase the message. `ESMSafetyTest` in `riddlLib/jvm/src/test/` enforces this by scanning the fullLinkJS bundle
685+
29. **Container.flatten() extension** - Recursively removes Include/BASTImport wrappers in-place. Lives in `language/shared/.../Contents.scala`. FlattenPass delegates to `root.flatten()`. Use base `Pass` not `DepthFirstPass` — mutating contents during traversal corrupts ArrayBuffer iteration
686+
30. **release.yml automates multi-platform builds** - Triggered by `gh release create`. Builds native riddlc on macOS ARM64, macOS x86_64, Linux x86_64, plus JVM. Auto-updates homebrew-tap formula with SHA256 hashes
687+
31. **Homebrew formula supports native + JVM fallback** - macOS ARM64 gets native binary (no JDK). Other platforms get JVM version with openjdk@21 dependency. Formula at `../homebrew-tap/Formula/riddlc.rb`

NOTEBOOK.md

Lines changed: 155 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ This is the central engineering notebook for the RIDDL project. It tracks curren
1212
compiler infinite loop bug with opaque types/intersection types in 3.3.x).
1313
All workflow paths updated to `scala-3.7.4`.
1414

15-
**Release 1.3.0 Published**: New features: OutlinePass, TreePass,
16-
and RiddlAPI `getOutline()`/`getTree()` methods for RIDDL definition
17-
hierarchy navigation. npm packaging via sbt-ossuminc 1.3.0. Published
18-
to GitHub Packages. Homebrew tap updated.
15+
**Release 1.4.0 Published**: New `Container.flatten()` extension
16+
method in the `language` module, rewritten `FlattenPass` using base
17+
`Pass` class, multi-platform release workflow. Native macOS ARM64
18+
binary now distributed via Homebrew (no JDK required).
1919

2020
**npm Package Published**: `@ossuminc/riddl-lib` published to GitHub
2121
Packages npm registry via CI and locally. ESModule format with TypeScript
@@ -32,8 +32,9 @@ tasks (`npmPublishGithub`/`npmPublishNpmjs`). Consumable via
3232
- `package.json.template` — Enhanced with TypeScript and ES module support
3333
- `pack-npm-modules.sh` — Updated with TypeScript definitions integration
3434

35-
**Homebrew Tap Updated**: `ossuminc/homebrew-tap` updated to 1.3.0.
36-
`brew install ossuminc/tap/riddlc` works.
35+
**Homebrew Tap Updated**: `ossuminc/homebrew-tap` updated to 1.4.0.
36+
macOS ARM64 gets native binary (no JDK dependency). Other platforms
37+
fall back to JVM version with openjdk@21.
3738

3839
**Branch Cleanup Complete**: All stale feature/bugfix branches deleted. Only `main`
3940
and `development` branches remain.
@@ -109,7 +110,41 @@ hand-maintained or auto-generated via a build step.
109110

110111
**File**: `riddlLib/js/types/index.d.ts`
111112

112-
### 3. AIHelperPass
113+
### 3. Add `RiddlLib.ast2bast` Function
114+
**Status**: Requested by Synapify team (February 5, 2026)
115+
116+
Add a convenience function to `RiddlLib` (the JS-exported API object)
117+
that converts a parsed AST to BAST bytes in a single call.
118+
119+
**Motivation**: Synapify needs to parse RIDDL in Electron's main
120+
process (Node.js, for filesystem access/include resolution) and
121+
transport the parsed AST to the renderer process via IPC. BAST binary
122+
format is the natural transport format since BASTWriter/BASTReader are
123+
already in the `language/shared` module (Scala.js compatible).
124+
125+
**Proposed API**:
126+
```scala
127+
// In RiddlLib or RiddlAPI:
128+
@JSExport
129+
def ast2bast(root: Root): js.typedarray.Int8Array = {
130+
val input = PassInput(root)
131+
val outputs = PassesOutput()
132+
val pass = BASTWriterPass(input, outputs)
133+
val result = Pass.runPass[BASTOutput](input, outputs, pass)
134+
js.typedarray.Int8Array.from(result.bytes)
135+
}
136+
```
137+
138+
**Details**:
139+
- Uses BASTWriterPass via the Pass framework for correct traversal
140+
- Returns `Int8Array` for efficient IPC transport (structured clone)
141+
- Synapify is prototyping this locally first, then will swap to the
142+
RiddlLib version when available
143+
- BASTReader.read(bytes) already provides the inverse operation
144+
- Consider also adding `bast2ast(bytes: Int8Array): js.Dynamic` for
145+
symmetry
146+
147+
### 4. AIHelperPass
113148
AI-friendly validation pass for MCP server integration. See design
114149
section below.
115150

@@ -224,6 +259,118 @@ The `pseudoCodeBlock` parser now allows comments before and/or after `???`:
224259

225260
## Session Log
226261

262+
### February 5, 2026 (FlattenPass, Release 1.4.0)
263+
264+
**Focus**: Implement FlattenPass per FLATTEN_PASS_SPEC.md for
265+
Synapify, add multi-platform release CI.
266+
267+
**Work Completed**:
268+
1. Added `clear()` and `remove()` extension methods to
269+
`Contents[CV]` opaque type
270+
2. Added `flatten()` extension method on `Container[CV]` in the
271+
`language` module — recursively removes Include/BASTImport
272+
wrappers, promoting children to parent container. Available
273+
without `passes` dependency.
274+
3. Rewrote `FlattenPass` to use base `Pass` (not `DepthFirstPass`)
275+
with no-op `process()`, delegating to `root.flatten()` in
276+
`result()`. Old implementation was buggy (computed new contents
277+
via splitAt/merge but never assigned back; also unsafe mutation
278+
during DepthFirstPass traversal).
279+
4. Created `FlattenPassTest` with 10 tests covering all spec
280+
scenarios: single Include, single BASTImport, nested includes,
281+
mixed nodes, ordering preservation, deep nesting, empty nodes,
282+
accessor visibility after flatten, Nebula support.
283+
5. Added Backward Compatibility Policy to CLAUDE.md — no breaking
284+
changes without deprecation through current major version.
285+
6. Released 1.4.0: tagged, clean test, published to GitHub Packages,
286+
created GitHub release with JVM + native ARM64 artifacts.
287+
7. Updated homebrew-tap formula: native macOS ARM64 primary (no JDK
288+
needed), JVM fallback for other platforms.
289+
8. Created `release.yml` workflow for automated multi-platform
290+
builds: macOS ARM64, macOS x86_64, Linux x86_64, plus JVM.
291+
Auto-updates homebrew formula with SHA256 hashes on release.
292+
293+
**Design Decisions**:
294+
- `flatten()` lives in `language` module as Container extension
295+
(not in `passes`) so any consumer can use it without the passes
296+
dependency
297+
- Base `Pass` instead of `DepthFirstPass` to avoid mutating
298+
contents during active ArrayBuffer iteration
299+
- Type parameter `Container[CV <: RiddlValue]` provides compile-
300+
time constraint while still requiring runtime cast for mixed-
301+
type Include/BASTImport contents
302+
303+
**Version Bump Rationale**: 1.3.1 → 1.4.0 (MINOR) — new public
304+
API (`Container.flatten()` extension, `Contents.clear()`,
305+
`Contents.remove()`), no breaking changes.
306+
307+
**Commits**:
308+
- `95608fcf` — Add Container.flatten() extension and rewrite
309+
FlattenPass
310+
- `a79f7a5a` — Add multi-platform release workflow
311+
312+
**Files Created**:
313+
- `passes/shared/.../transforms/FlattenPassTest.scala`
314+
- `.github/workflows/release.yml`
315+
316+
**Files Modified**:
317+
- `language/shared/.../Contents.scala` — clear, remove, flatten
318+
- `passes/shared/.../transforms/FlattenPass.scala` — rewritten
319+
- `CLAUDE.md` — backward compatibility policy
320+
321+
**Cross-project**: `../homebrew-tap/Formula/riddlc.rb` → 1.4.0
322+
with native ARM64 support
323+
324+
---
325+
326+
### February 5, 2026 (ESM Shim Fix, Release 1.3.1)
327+
328+
**Focus**: Fix string literals that trigger ESM shim plugin
329+
rewriting in downstream JS projects, add regression test.
330+
331+
**Problem**: ESM shim plugins (Vite esmShimPlugin) scan JS bundles
332+
for `import '…`, `import "…`, and `import(…` patterns and rewrite
333+
them. String literals in shared Scala source containing these
334+
patterns ended up in the riddl-lib JS bundle, corrupting downstream
335+
builds.
336+
337+
**Work Completed**:
338+
1. Found 7 occurrences across 4 shared-source files:
339+
- `AST.scala` (2, HIGH risk — exact ES import syntax)
340+
- `BASTLoader.scala` (1, MED)
341+
- `ValidationPass.scala` (2, LOW-MED)
342+
- `TopLevelParser.scala` (2, LOW)
343+
2. Fixed all: split keyword via `val imp = "im" + "port"` for
344+
format output; rephrased error messages to use "BAST file"
345+
or "BAST load" instead of "BAST import"
346+
3. Added explanatory comments at each location warning future
347+
developers not to reintroduce the pattern
348+
4. Created `ESMSafetyTest` (`riddlLib/jvm/src/test/`) that:
349+
- Locates fullLinkJS output via glob (Scala-version agnostic)
350+
- Scans the 5MB JS bundle for dangerous patterns
351+
- Reports file path + size when scanning (distinguishes from
352+
skip)
353+
- Skips gracefully via `assume` if bundle not built
354+
5. Released 1.3.1 — tagged, clean build, all tests pass, published
355+
to GitHub Packages, GitHub release created, homebrew-tap updated
356+
357+
**Commits**:
358+
- `1272df2d` — Fix string literals that trigger ESM shim rewriting
359+
- `330b6593` — Add ESM safety regression test for JS bundle
360+
361+
**Files Created**:
362+
- `riddlLib/jvm/src/test/scala/.../ESMSafetyTest.scala`
363+
364+
**Files Modified**:
365+
- `language/shared/.../AST.scala` — split `import` keyword
366+
- `language/shared/.../bast/BASTLoader.scala` — rephrase message
367+
- `language/shared/.../parsing/TopLevelParser.scala` — rephrase
368+
- `passes/shared/.../validate/ValidationPass.scala` — rephrase
369+
370+
**Cross-project**: `../homebrew-tap/Formula/riddlc.rb` → 1.3.1
371+
372+
---
373+
227374
### February 5, 2026 (OutlinePass, TreePass, Release 1.3.0)
228375

229376
**Focus**: Implement getOutline/getTree RiddlAPI methods and release
@@ -1262,4 +1409,4 @@ Tool(
12621409
## Git Information
12631410

12641411
**Branch**: `development`
1265-
**Latest release**: 1.3.0 (February 5, 2026)
1412+
**Latest release**: 1.4.0 (February 5, 2026)

0 commit comments

Comments
 (0)