semantifold 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +6 -3
  2. package/build/index.d.ts +8 -8
  3. package/build/index.d.ts.map +1 -1
  4. package/build/index.js +6 -6
  5. package/build/src/backends/android.js +2 -2
  6. package/build/src/backends/dart.d.ts +19 -0
  7. package/build/src/backends/dart.d.ts.map +1 -1
  8. package/build/src/backends/dart.js +28 -16
  9. package/build/src/backends/flutter.d.ts +51 -0
  10. package/build/src/backends/flutter.d.ts.map +1 -0
  11. package/build/src/backends/flutter.js +1362 -0
  12. package/build/src/backends/identifiers.js +5 -5
  13. package/build/src/backends/program.d.ts +4 -4
  14. package/build/src/backends/program.d.ts.map +1 -1
  15. package/build/src/backends/program.js +4 -4
  16. package/build/src/backends/shared.d.ts +7 -0
  17. package/build/src/backends/shared.d.ts.map +1 -1
  18. package/build/src/backends/shared.js +11 -6
  19. package/build/src/language-registry.d.ts.map +1 -1
  20. package/build/src/language-registry.js +11 -1
  21. package/build/src/semantic/types.d.ts +152 -2
  22. package/build/src/semantic/types.d.ts.map +1 -1
  23. package/build/src/semantic/types.js +38 -2
  24. package/docs/android.md +6 -2
  25. package/docs/architecture.md +2 -0
  26. package/docs/flutter.md +47 -0
  27. package/docs/goals.md +1 -1
  28. package/docs/language-support.md +9 -2
  29. package/docs/source-maps.md +2 -0
  30. package/docs/testing.md +22 -1
  31. package/index.js +5 -5
  32. package/package.json +1 -1
  33. package/src/backends/android.js +1 -1
  34. package/src/backends/dart.js +28 -15
  35. package/src/backends/flutter.js +1465 -0
  36. package/src/backends/identifiers.js +4 -4
  37. package/src/backends/program.js +3 -3
  38. package/src/backends/shared.js +12 -8
  39. package/src/language-registry.js +10 -0
  40. package/src/semantic/types.js +40 -1
@@ -0,0 +1,47 @@
1
+ # Flutter application target
2
+
3
+ Task 030 adds the target-only `flutter` application backend. Flutter is not a source language: callers parse any existing source language into a semantic module or Task 010 program, then request an application artifact set.
4
+
5
+ ```js
6
+ const program = parseProgram({entryModule: "main", sources})
7
+ const project = generateProgramArtifactSet({
8
+ language: "flutter",
9
+ program,
10
+ role: "application"
11
+ })
12
+ ```
13
+
14
+ The current qualified slice is Android-only. Every generated path is below `generated/flutter-app`; no iOS runner is emitted. macOS, Xcode, Apple SDK, CocoaPods, signing, iOS Simulator build/launch, and iOS UI proof remain explicitly deferred by owner direction. The registry and project manifest report that boundary rather than treating an absent Apple toolchain as a skip or claiming dual-platform completion.
15
+
16
+ ## Application and package contract
17
+
18
+ The backend accepts exactly the semantic subset already supported by the Dart backend. It emits mapped, namespaced Dart parts plus a synthetic stateless Material shell. Each invocation creates a fresh output sink, executes the semantic entry, joins printed values with LF, and displays the exact result below `Key('semantifold-output')` and the `semantifold-output` semantics label. Widget lifecycle and platform-runner behavior do not enter semantic IR.
19
+
20
+ The emitted template is owned and versioned by Semantifold; generation never invokes `flutter create`. Its Android configuration excludes the inactive profile-installer optimization and removes the SDK embedding's dynamic-receiver permission and startup provider; final-APK acceptance requires zero permissions, providers, receivers, or services. Its package manifest has only direct Flutter-SDK dependencies:
21
+
22
+ - `flutter` from the SDK;
23
+ - `flutter_test` from the SDK as a development dependency.
24
+
25
+ The exact lockfile records the transitive test/runtime packages shipped in the checksum-qualified Flutter archive. Restore is always offline from the archive's preload cache and uses `--enforce-lockfile`; application generation and tests never download a pub package. There are no plugins, platform channels, permissions, external packages, embedded source runtimes, network/storage/background behavior, navigation, or mutable widget state.
26
+
27
+ Configuration is a closed record. Defaults are `semantifold_generated`, organization `dev.semantifold`, application ID `dev.semantifold.generated`, activity `MainActivity`, display name `Semantifold`, version `1.0.0+1`, minimum SDK 23, target/compile SDK 35, and Build Tools 35.0.0. Package and reverse-DNS identities, Java activity name, Unicode display name, version values, the empty permission set, and the exact Android matrix are validated before rendering. A root package name cannot collide with any SDK or hosted package in the owned lockfile, and the launcher class cannot collide with its imported `FlutterActivity` base class.
28
+
29
+ Assets are explicit closed records `{path, content, mediaType, sha256}` below `assets/`. Content is detached before return. Traversal, absolute or unsafe paths, Unicode/case collisions, file-prefix collisions, generated-path conflicts, malformed media types, empty content, and checksum mismatches fail transactionally.
30
+
31
+ ## Ownership and provenance
32
+
33
+ `SemantifoldFlutterProject` version 1 records every owned path and SHA-256, excluded cache/build/local-configuration paths, normalized configuration and exact output ranges, asset hashes, semantic source/module/import/entry identities, synthetic scaffolding, platform status, and toolchain identity. Dart semantic tokens—including ordinary source `print` syntax—preserve rich mappings and Source Map v3 projections to all original source files. The Flutter output sink, Material widgets, tests, Android runner, Gradle files, manifests, resources, and template metadata are synthetic or configuration-derived. Generated zero-argument declarations and calls retain the pinned Dart formatter's multiline layout before toolchain validation.
34
+
35
+ The private acceptance materializer writes only to one caller-created empty, real, mode-0700 directory. It uses exclusive creation, reads every file back, verifies checksums, removes partial generated output on failure, and is neither exported nor packed. Generated `android/local.properties`, caches, debug keys, Gradle outputs, and APKs belong only to disposable acceptance state.
36
+
37
+ ## Exact Android qualification
38
+
39
+ Flutter is pinned to stable `3.47.4`, framework revision `9584c6713b324636289d067944a46fd6b49df14b`, bundled Dart `3.13.3`, archive size `1576174568`, and SHA-256 `5b45f0ceda99b9bebdc873e7e69f6450aeb4c30f454b505e2e62fc9255a907d3`. The generated Android project reuses Task 028's API-35/Build-Tools-35.0.0, AGP 8.11.1, JDK 21.0.8, emulator 35.6.11, private signing root, and sole TensorBuzz `/dev/kvm` topology. Its engine build pins Kotlin Gradle plugin 2.2.20, NDK 27.0.12077973, and CMake 3.22.1; Kotlin's implicit standard-library dependency remains disabled and generated applications contain no Kotlin source or user native code. The shared Gradle baseline advances to checksum-pinned 8.14 because Flutter 3.47.4 rejects 8.13; dependency validation is not bypassed and no second Gradle/cache topology is introduced.
40
+
41
+ Online bootstrap downloads only the exact Flutter archive, validates it before installation, seeds the isolated pub cache from its 186 included preload archives, and warms the already-shared Gradle cache with a disposable project. Offline acceptance then enforces the lockfile, checks formatter canonicality, runs analyzer with fatal warnings/information, runs real Flutter unit/widget tests, and runs Android lint and debug assembly. It verifies the exact package graph, SDK-owned Flutter embedding, empty declared permission surface, and produced APK.
42
+
43
+ The existing Android emulator script remains the only device lane and still performs exactly two fresh hardware-accelerated API-35 boots. Each boot retains the native Task 028 proof, then installs and launches the Flutter APK, captures UI XML and a screenshot, and requires exactly one `semantifold-output` Android semantics descriptor with exactly one descendant descriptor containing the exact Unicode output. Native same-node text and the previously owned combined descriptor remain accepted exact forms. Failure diagnostics report the observed descriptor/text values without accepting unrelated UI text. Missing KVM, SDK artifacts, cached dependencies, tools, label, output, or clean teardown fails loudly. Local environments without KVM do not substitute software emulation.
44
+
45
+ ## Deferred and excluded work
46
+
47
+ No result from this slice establishes iOS support. Dual-platform Task 030 completion remains blocked on separately authorized real Apple toolchain and iOS Simulator proof. Web/desktop Flutter, arbitrary widgets/state/navigation, plugins, platform channels, host APIs, external pub packages, native extensions, physical devices, release signing, store upload, and deployment remain outside the baseline.
package/docs/goals.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Semantifold's long-term goal is a language-neutral toolkit for understanding, transforming, generating, and eventually executing programs through a shared high-level semantic representation. The representation should make types, control flow, calls, declarations, diagnostics, and source provenance understandable without exposing a language parser's private tree.
4
4
 
5
- The current source tree proves one minimal Tasks 001–004 vertical slice across fifteen registered source languages: PHP, Ruby, JavaScript, TypeScript, Java, Kotlin/JVM, strictly annotated Python, canonical C#, bounded Go, C17, C++20, Rust edition 2021, Swift, Dart, and Zig. Dart and Zig additionally implement the bounded Task 005 required-function/call profile; the original five retain the delivered Task 013 acceptance gate for the combined Tasks 001–008 profile, Task 009 nominal closed records, Task 010 explicit acyclic multi-source semantic programs, Task 011 exact nominal typed unchecked errors, and Task 012 invariant unbounded function/record type parameters with closed applications and argument-only first-order call inference. Task 014 is delivered through PR #41, Task 032 through PR #42, Task 033 through PR #43, and Task 034 through PR #44. Task 035 is delivered through PR #45 and merge commit `a2aad9d4932bfc6087adc4ff8bca43678c92413c`, with versioned canonical standard-library contracts, target host providers and protected native bindings, capability negotiation, and program-mode provider linking. Task 036 is delivered through PR #46 and merge `9aba48f9d48bcef4fd4c9275aec14bfcc4f0904c`; it adds bounded versioned executable qualification facades and exact parser-backed native identity resolution for the original five. Task 037 adds only the first concrete Ruby-source-to-PHP-target blocking TCP/line-output slice on those foundations. The source tree includes versioned source provenance, deterministic semantic node/symbol identity, range-based generated mappings, Source Map v3 interop, composition, and diagnostic remapping across those bounded profiles. The published `semantifold@0.5.0` release predates Task 031. Neither the source tree nor that release provides a general analyzer, transformation API, interpreter, optimizer, implicit project/package discovery, debugger integration, coverage remapping, or lossless formatter.
5
+ The current source tree proves one minimal Tasks 001–004 vertical slice across fifteen registered source languages: PHP, Ruby, JavaScript, TypeScript, Java, Kotlin/JVM, strictly annotated Python, canonical C#, bounded Go, C17, C++20, Rust edition 2021, Swift, Dart, and Zig. Dart and Zig additionally implement the bounded Task 005 required-function/call profile; the original five retain the delivered Task 013 acceptance gate for the combined Tasks 001–008 profile, Task 009 nominal closed records, Task 010 explicit acyclic multi-source semantic programs, Task 011 exact nominal typed unchecked errors, and Task 012 invariant unbounded function/record type parameters with closed applications and argument-only first-order call inference. Task 014 is delivered through PR #41, Task 032 through PR #42, Task 033 through PR #43, and Task 034 through PR #44. Task 035 is delivered through PR #45 and merge commit `a2aad9d4932bfc6087adc4ff8bca43678c92413c`, with versioned canonical standard-library contracts, target host providers and protected native bindings, capability negotiation, and program-mode provider linking. Task 036 is delivered through PR #46 and merge `9aba48f9d48bcef4fd4c9275aec14bfcc4f0904c`; it adds bounded versioned executable qualification facades and exact parser-backed native identity resolution for the original five. Task 037 adds only the first concrete Ruby-source-to-PHP-target blocking TCP/line-output slice on those foundations. The source tree includes versioned source provenance, deterministic semantic node/symbol identity, range-based generated mappings, Source Map v3 interop, composition, and diagnostic remapping across those bounded profiles. The published `semantifold@0.6.0` and annotated `v0.6.0` target exact commit `f76e6d64b388d65959e77f747ae2d60a999d61f5`, including Task 028 from PR #51 and Task 031 from PR #52. Neither the source tree nor that release provides a general analyzer, transformation API, interpreter, optimizer, implicit project/package discovery, debugger integration, coverage remapping, or lossless formatter.
6
6
 
7
7
  The long-term product direction includes bounded standard-library portability through [language compatibility stdlib/facades, canonical Semantifold stdlib contracts/capabilities, and target host providers/native bindings](standard-library-portability.md). That direction is incremental and versioned; it does not promise arbitrary standard-library coverage or arbitrary-application translation. The `0.3.0` release has no imports, classes or methods, loops, optional values, typed errors, resources, host APIs, or stdlib portability.
8
8
 
@@ -24,8 +24,9 @@ The immutable registry is authoritative for both dispatch and discovery:
24
24
  | `wasm` | no | no | yes | yes | no | no | no | no | no | no | no | no | no | no | no | no | multiple | no | rich text + v3 + byte ranges | generate, validate, instantiate, execute (`wasm-validate`, `node`, `chromium`) |
25
25
  | `ios` | no | no | no | yes | no | no | no | no | no | no | no | no | no | no | no | no | multiple | no | rich text + v3 + byte ranges | generate (Apple acceptance deferred) |
26
26
  | `android` | no | no | no | yes | no | no | no | no | no | no | no | no | no | no | no | no | multiple | no | rich text + v3 + byte ranges | generate, compile, validate, instantiate, execute (`android`, TensorBuzz KVM) |
27
+ | `flutter` | no | no | no | yes | no | no | no | no | no | no | no | no | no | no | no | no | multiple | no | rich text + v3 + byte ranges | generate, restore, compile, validate, instantiate, execute (`flutter`, `android`; Android qualified, iOS deferred) |
27
28
 
28
- `languageCapabilities` exposes all eighteen records as frozen data, including `features.generalFunctionsAndCalls`, `features.immutableCollections`, `features.optionalValues`, `features.orderedListIteration`, `features.orderedMapIteration`, `features.conditionControlledLoops`, `features.referenceClasses`, `features.effectfulCapabilitiesAndResources`, `features.closedRecords`, `features.typedErrors`, and `features.typeParametersAndGenerics`. A role or semantic feature is not inferred from another role: browser Wasm has binary/application backends without a frontend or text backend, while `ios` and `android` have only application backends. None has a source round trip or general interoperability role; Android retains the Kotlin/JVM Tasks 001–004 function subset while adding resolved Task 010 module linkage in its application shell. `supportedLanguages` is the derived list of fifteen records with both frontend and text generation. C#, Go, C, and Zig return two text artifacts; Rust and Dart return three; Wasm returns one binary and three text artifacts; iOS and Android return deterministic multi-artifact application projects. Their callers use `generateArtifactSet()`; the legacy single-artifact APIs reject unavailable roles with `UNSUPPORTED_ROLE`.
29
+ `languageCapabilities` exposes all nineteen records as frozen data, including `features.generalFunctionsAndCalls`, `features.immutableCollections`, `features.optionalValues`, `features.orderedListIteration`, `features.orderedMapIteration`, `features.conditionControlledLoops`, `features.referenceClasses`, `features.effectfulCapabilitiesAndResources`, `features.closedRecords`, `features.typedErrors`, and `features.typeParametersAndGenerics`. A role or semantic feature is not inferred from another role: browser Wasm has binary/application backends without a frontend or text backend, while `ios`, `android`, and `flutter` have only application backends. None has a source round trip or general interoperability role; Android retains the Kotlin/JVM Tasks 001–004 function subset, while Flutter consumes the independent Dart Tasks 001–005 capability subset and both add resolved Task 010 linkage in their application shells. `supportedLanguages` is the derived list of fifteen records with both frontend and text generation. C#, Go, C, and Zig return two text artifacts; Rust and Dart return three; Wasm returns one binary and three text artifacts; iOS, Android, and Flutter return deterministic multi-artifact application projects. Their callers use `generateArtifactSet()`; the legacy single-artifact APIs reject unavailable roles with `UNSUPPORTED_ROLE`.
29
30
 
30
31
  ## Task 026 iOS application generation
31
32
 
@@ -39,6 +40,12 @@ The `android` registry row is an application-only target over the independent Ko
39
40
 
40
41
  The generated build declares only exact non-transitive `testImplementation("junit:junit:4.13.2")` and `testRuntimeOnly("org.hamcrest:hamcrest-core:1.3")`; Kotlin's implicit stdlib dependency is disabled and no library enters the application runtime classpath. Official tool/cache preparation is online, but lint, unit, application APK, instrumentation APK, dependency inspection, and APK leakage checks execute with Gradle offline. TensorBuzz's `/dev/kvm` lane performs two fresh accelerated API-35 emulator boots with exact labelled-text and lifecycle assertions. No local software-emulator fallback, public writer, signing/store route, permission, service, Compose, WebView, NDK/JNI, source runtime, or platform channel exists. See [Android application target](android.md).
41
42
 
43
+ ## Task 030 Flutter application generation
44
+
45
+ The `flutter` registry row is application-only and does not add a sixteenth frontend. It accepts exactly the semantic project subset supported by the Dart backend, emits mapped per-module Dart plus a synthetic stateless Material shell, and owns a versioned Android Flutter template below `generated/flutter-app`. Exact package identity, the SDK-only pubspec/lock, assets, paths, hashes, configuration causality, semantic provenance, and platform/toolchain status are validated before any artifact set is returned.
46
+
47
+ Flutter stable 3.47.4 with bundled Dart 3.13.3 is checksum-pinned. Offline restore uses only its archive preload cache; format, analyzer, Flutter widget tests, Android lint/build, and exact labelled Unicode UI assertion are real. The one Task 028 Gradle cache advances to 8.14 for Flutter compatibility, while its JDK/AGP/API/build-tools/emulator values and exactly two KVM boots remain shared. No plugin, platform channel, permission, external pub package download, source runtime, public writer, or second Android topology exists. iOS runner artifacts are deliberately omitted and every Apple build/launch/UI gate remains deferred rather than silently skipped. See [Flutter application target](flutter.md).
48
+
42
49
  ## Task 025 core expanded-language acceptance
43
50
 
44
51
  Python, C#, C, C++, Rust, Swift, Kotlin/JVM, and Go share one data-driven Tasks 001–004 acceptance gate. Their five base/scalar/local/operator/statement fixtures normalize to the same location-neutral semantic corpus; the pre-existing `select`/`choose` spelling difference is treated as a reserved-word adaptation only, not different behavior. Each backend generates, reparses, and runs the complete operator profile through its real registered toolchain. Python and Swift emit one source file; C++ emits one source file; C# and C emit two-file projects; Rust emits `Cargo.toml`, `Cargo.lock`, and `src/main.rs`; Kotlin emits mapped `Program.kt` with runnable-JAR metadata; and Go emits `go.mod` plus `main.go`.
@@ -300,7 +307,7 @@ Binary/application generation returns `program.wasm`, `program.wasm.map`, `seman
300
307
 
301
308
  ### Bounded standard-library portability
302
309
 
303
- The registered language roles cover only the semantic subset documented above. `semantifold@0.3.0` has no standard-library symbol identities, compatibility facade, or host-provider linking. The current source tree adds Task 032 condition-controlled loops, Task 033 bounded reference classes, Task 034's effect/resource foundation, Task 035's delivered versioned canonical contract/provider-linking hub from PR #45, and Task 036's delivered neutral facade qualification layer from PR #46. The published release lacks all of these additions.
310
+ The registered language roles cover only the semantic subset documented above. The `semantifold@0.6.0` release contains the Task 032 condition-controlled loops, Task 033 bounded reference classes, Task 034 effect/resource foundation, Task 035 versioned canonical contract/provider-linking hub, Task 036 neutral facade qualification layer, Task 037 bounded TCP vertical slice, Task 028 Android application target, and Task 031 Zig target. Task 030 is the subsequent bounded Flutter application candidate described above; it does not broaden standard-library portability.
304
311
 
305
312
  Task 037 adds exactly one concrete lane: Ruby source targeting PHP. The Ruby frontend accepts only literal `require "socket"`, genuine `TCPSocket.new(host, port)`, zero-argument receiver `gets` and `close`, and exactly one string argument to unqualified `puts` or `Kernel.puts`. The output builtin is resolved only inside that same parser-proved socket profile, preserving legacy Ruby program-mode `puts` elsewhere. User-defined/shadowed/reopened/monkey-patched identities, dynamic require/send, blocks, other members, extra arguments, coercive or multi-value output, and timeout or socket options fail at their parser-backed locations.
306
313
 
@@ -130,6 +130,8 @@ The iOS project manifest adds an application-specific provenance index without w
130
130
 
131
131
  The Android project uses the same separation without sharing platform syntax with iOS. Every per-module semantic Kotlin artifact has authoritative rich/v3 mappings to all Task 010 source identities and filenames. Gradle, manifest, Activity, lifecycle, layout, resources, runtime, and test artifacts are synthetic or configuration-derived. `SemantifoldAndroidProject` version 1 records field-owned output ranges, exact input and output hashes, fixed-root ownership/exclusions, semantic module/dependency/source/entry linkage, and exact toolchain pins. Binary caller inputs retain full byte provenance. See [Android application target](android.md).
132
132
 
133
+ The Flutter project preserves the same separation through the independent Dart lowering. Each generated semantic Dart part retains rich mappings and a Source Map v3 projection to all originating Task 010 files, while the shared output sink, Material widget shell, SDK/package configuration, Android runner, resources, and tests are synthetic or configuration-derived. `SemantifoldFlutterProject` version 1 records configuration-owned output ranges, exact asset and artifact hashes, fixed-root ownership/exclusions, semantic module/dependency/source/entry linkage, exact Flutter/Android toolchains, and the explicit omission/deferment of iOS artifacts and proof. See [Flutter application target](flutter.md).
134
+
133
135
  ## Source Map v3 and directives
134
136
 
135
137
  `artifact.sourceMap` exists for all single-text target artifacts and mapped multi-artifact text outputs; browser Wasm additionally has the external binary projection described above. Maps are generated with `@jridgewell/gen-mapping`, while lookup, import, artifact validation, and independent test decoding use `@jridgewell/trace-mapping`. Semantifold does not hand-code VLQ or tracing. Text artifact validation requires dense `sources`, `names`, and optional `sourcesContent` arrays, canonical standard segments, valid indexes, and equality with the authoritative rich mapping projection. The v3 map contains deterministic `file`, `sources`, `sourcesContent`, `names`, and `mappings` fields.
package/docs/testing.md CHANGED
@@ -504,7 +504,28 @@ npx velocious-test spec/android-packed-consumer.spec.js
504
504
 
505
505
  Generation coverage validates multi-module/Unicode capture, mappings, configuration causality, deterministic fixed-root ownership, manifest/UI/dependency shape, resources/assets, collisions, and preflight diagnostics. Materialization is repository-private acceptance support: it requires an empty mode-0700 non-symlink directory, creates files exclusively, verifies checksum readback, and is neither exported nor packed. The packed proof uses clean public-registry npm install/ci and strict TypeScript consumption.
506
506
 
507
- TensorBuzz's Android lane runs `scripts/bootstrap-android.sh` online to checksum and prefetch only the qualified official toolchain/cache, including the exact Kotlin 2.2.10 compiler distribution used as a direct compiler input while implicit Gradle stdlib resolution stays disabled. The same pinned stdlib file is the sole Kotlin runtime packaged into the generated instrumentation APK. `scripts/accept-android.sh` then creates a fresh project and runs lint, JUnit, application/instrumentation assembly, dependency inspection, and APK leakage checks with `--offline`. It requires an empty application runtime graph; the unit-test graph must contain exactly non-transitive JUnit 4.13.2 at implementation scope and Hamcrest Core 1.3 at runtime scope because the JUnit runner loads Hamcrest before test code. Neither unit-test dependency nor Kotlin runtime implementation namespaces may appear in the app APK, while the instrumentation APK must contain `kotlin.jvm.internal.Intrinsics`. `scripts/android-emulator-acceptance.sh` requires usable `/dev/kvm`, forces acceleration, installs/launches/asserts exact base64-encoded UTF-8 output through platform instrumentation, captures UI XML/screenshots, destroys the emulator, and repeats on a fresh boot. Missing tools/cache/KVM are infrastructure failures, never skips. Do not run this emulator script locally without KVM or substitute software emulation.
507
+ TensorBuzz's Android lane runs `scripts/bootstrap-android.sh` online to checksum and prefetch only the qualified official toolchain/cache, including the exact Kotlin 2.2.10 compiler distribution used as a direct compiler input while implicit Gradle stdlib resolution stays disabled. The same pinned stdlib file is the sole Kotlin runtime packaged into the generated instrumentation APK. `scripts/accept-android.sh` then creates a fresh project and runs lint, JUnit, application/instrumentation assembly, dependency inspection, and APK leakage checks with `--offline`. It requires an empty application runtime graph; the unit-test graph must contain exactly non-transitive JUnit 4.13.2 at implementation scope and Hamcrest Core 1.3 at runtime scope because the JUnit runner loads Hamcrest before test code. Neither unit-test dependency nor Kotlin runtime implementation namespaces may appear in the app APK, while the instrumentation APK must contain `kotlin.jvm.internal.Intrinsics`. `scripts/android-emulator-acceptance.sh` requires usable `/dev/kvm`, forces acceleration, installs/launches/asserts exact base64-encoded UTF-8 output through platform instrumentation, then performs the Task 030 Flutter launch/UI proof on the same boot before destroying the emulator and repeating everything on one fresh boot. Missing tools/cache/KVM are infrastructure failures, never skips. Do not run this emulator script locally without KVM or substitute software emulation.
508
+
509
+ ## Task030 Flutter application acceptance
510
+
511
+ Run the Flutter files individually and sequentially:
512
+
513
+ ```sh
514
+ npx velocious-test spec/flutter-application.spec.js
515
+ npx velocious-test spec/flutter-materialization.spec.js
516
+ npx velocious-test spec/flutter-ui-assertion.spec.js
517
+ npx velocious-test spec/flutter-toolchain-contract.spec.js
518
+ npx velocious-test spec/flutter-packed-consumer.spec.js
519
+ npx velocious-test spec/language-registry.spec.js
520
+ ```
521
+
522
+ Generation coverage includes Ruby- and Dart-originating programs, multiple modules, Unicode, exact widget output, registry/public-role separation, package/plugin/permission closure, deterministic ownership and hashes, rich source/configuration provenance, asset snapshots, unsafe identifiers/configuration/paths/collisions, unsupported semantics, and transactional rejection. Private materialization requires a fresh real mode-0700 root and verifies every byte without creating a public or packed writer. The packed proof repeats credential-free ordinary install and clean `npm ci` plus strict TypeScript consumption.
523
+
524
+ Real local SDK qualification uses exact Flutter 3.47.4 revision `9584c6713b324636289d067944a46fd6b49df14b` and its bundled Dart 3.13.3. Seed a fresh isolated `PUB_CACHE` only with the checksum-qualified archive's `.pub-preload-cache/*.tar.gz`; then the generated project must pass `dart pub get --offline --enforce-lockfile`, `dart format --output=none --set-exit-if-changed lib test`, Flutter analyze with `--no-pub --fatal-infos --fatal-warnings`, and Flutter test with `--no-pub`. No command may invoke `flutter create`, download a pub package, or rewrite the owned lockfile.
525
+
526
+ TensorBuzz retains one `android` build and exactly `/dev/kvm:/dev/kvm`. After the Task 028 bootstrap, `scripts/bootstrap-flutter.sh` verifies the official SDK archive's size/SHA/revision, seeds its isolated pub cache, and warms the same Gradle cache with a disposable project. `scripts/accept-flutter.sh` repeats restore, format, analyze, widget tests, lint, assembly, package graph, embedding, and APK-permission checks offline. The existing emulator script then installs and launches the Flutter APK during each of its two Task 028 fresh boots, requires exact `hé😀\nhé😀!\nhé😀!?` output under `semantifold-output`, and captures Flutter UI XML/screenshots. Flutter 3.47.4 requires the single shared Gradle 8.14 baseline; bypassing dependency validation or creating a second cache/emulator topology is forbidden.
527
+
528
+ These checks qualify only Android. No local or TensorBuzz step provisions or invokes macOS, Xcode, Apple SDK, CocoaPods, signing, or an iOS Simulator. No omitted Apple prerequisite is reported as a skip or success; dual-platform Task 030 completion remains deferred.
508
529
 
509
530
  ## Task022 Swift acceptance
510
531
 
package/index.js CHANGED
@@ -97,8 +97,8 @@ export function generateArtifact(input) {
97
97
  * @param {import("./src/semantic/types.js").BackendLanguage} input.language - Registered program target.
98
98
  * @param {import("./src/semantic/types.js").SemanticProgram} input.program - Complete resolved program.
99
99
  * @param {"text" | "application"} [input.role] - Explicit role; omitted preserves text generation.
100
- * @param {import("./src/semantic/types.js").IosApplicationConfigurationInput | import("./src/semantic/types.js").AndroidApplicationConfigurationInput} [input.configuration] - Application configuration.
101
- * @param {import("./src/semantic/types.js").IosApplicationAssetInput[] | import("./src/semantic/types.js").AndroidApplicationInputFile[]} [input.assets] - Exact caller assets.
100
+ * @param {import("./src/semantic/types.js").IosApplicationConfigurationInput | import("./src/semantic/types.js").AndroidApplicationConfigurationInput | import("./src/semantic/types.js").FlutterApplicationConfigurationInput} [input.configuration] - Application configuration.
101
+ * @param {import("./src/semantic/types.js").IosApplicationAssetInput[] | import("./src/semantic/types.js").AndroidApplicationInputFile[] | import("./src/semantic/types.js").FlutterApplicationAssetInput[]} [input.assets] - Exact caller assets.
102
102
  * @param {import("./src/semantic/types.js").AndroidApplicationInputFile[]} [input.resources] - Exact Android caller resources.
103
103
  * @returns {import("./src/semantic/types.js").GeneratedArtifactSet} Complete generated set.
104
104
  */
@@ -116,8 +116,8 @@ export function generateProgramArtifactSet(input) {
116
116
  * @param {"none" | "external" | "inline"} [input.mapDirective] - JavaScript-family map directive.
117
117
  * @param {string} [input.sourceMapFilename] - External map filename.
118
118
  * @param {{filename: string, content: string, language?: import("./src/semantic/types.js").SemanticLanguage}[]} [input.sources] - Original sources.
119
- * @param {import("./src/semantic/types.js").IosApplicationConfigurationInput | import("./src/semantic/types.js").AndroidApplicationConfigurationInput} [input.configuration] - Application configuration.
120
- * @param {import("./src/semantic/types.js").IosApplicationAssetInput[] | import("./src/semantic/types.js").AndroidApplicationInputFile[]} [input.assets] - Exact caller assets.
119
+ * @param {import("./src/semantic/types.js").IosApplicationConfigurationInput | import("./src/semantic/types.js").AndroidApplicationConfigurationInput | import("./src/semantic/types.js").FlutterApplicationConfigurationInput} [input.configuration] - Application configuration.
120
+ * @param {import("./src/semantic/types.js").IosApplicationAssetInput[] | import("./src/semantic/types.js").AndroidApplicationInputFile[] | import("./src/semantic/types.js").FlutterApplicationAssetInput[]} [input.assets] - Exact caller assets.
121
121
  * @param {import("./src/semantic/types.js").AndroidApplicationInputFile[]} [input.resources] - Exact Android caller resources.
122
122
  * @returns {import("./src/semantic/types.js").GeneratedArtifactSet} Complete generated set.
123
123
  */
@@ -221,6 +221,6 @@ export function generateArtifactSet(input) {
221
221
  const registryRole = role == "binary" ? "binaryBackend" : "applicationBackend"
222
222
  const backend = languageRegistry.resolve(language, registryRole, module?.location)
223
223
 
224
- return constructArtifactSet(backend(language == "android" ? input :
224
+ return constructArtifactSet(backend(language == "android" || language == "flutter" ? input :
225
225
  {assets, configuration, filename, language, mapDirective, module, resources, sourceMapFilename, sources}))
226
226
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "semantifold",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Language-neutral semantic code analysis, transformation, generation, and execution toolkit",
5
5
  "type": "module",
6
6
  "main": "build/index.js",
@@ -74,7 +74,7 @@ const toolchain = Object.freeze({
74
74
  commandLineTools: "11076708",
75
75
  compileSdk: 35,
76
76
  emulator: "35.6.11",
77
- gradle: "8.13",
77
+ gradle: "8.14",
78
78
  java: "21.0.8",
79
79
  kotlin: "2.2.10",
80
80
  kotlinCompilerSha256: "302d1d8e671e5c3207e6ed62ff11fb555462a628e22a1158254dcaaf7e7394bc",
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {unsupportedCapability} from "../diagnostic.js"
4
4
  import {finalizeMapping, toSourceMapV3} from "../mapping.js"
5
- import {emitExpression, validateBackendModule} from "./shared.js"
5
+ import {emitExpression, flatDartExpression, validateBackendModule} from "./shared.js"
6
6
  import {dartRuntime} from "./dart-runtime.js"
7
7
  import {emitScalarType} from "./scalars.js"
8
8
  import {SourceWriter} from "./writer.js"
@@ -23,7 +23,7 @@ export function generateDartPackage({filename, mapDirective, module, sourceMapFi
23
23
  if (mapDirective !== undefined || sourceMapFilename !== undefined) {
24
24
  unsupportedCapability("dart", "source-map filename or directive option", module.location)
25
25
  }
26
- const unreadLocals = findUnreadLocals(module)
26
+ const unreadLocals = findUnreadDartLocals(module)
27
27
  const writer = new SourceWriter({filename: "bin/program.dart", language: "dart", module, sources})
28
28
 
29
29
  emitProgram(module, writer, unreadLocals)
@@ -113,12 +113,12 @@ function emitProgram(module, writer, unreadLocals) {
113
113
  writer.synthetic(" ", "body spacing", [declaration], [path])
114
114
  writer.mapped("{", {mappingKind: "anchor", node: declaration.body, path: `${path}/body`})
115
115
  writer.synthetic("\n", "line break", [declaration], [path])
116
- emitBlock(writer, declaration.body, " ", `${path}/body`, unreadLocals)
116
+ emitDartBlock(writer, declaration.body, " ", `${path}/body`, unreadLocals)
117
117
  writer.mapped("}", {mappingKind: "anchor", node: declaration.body, path: `${path}/body`})
118
118
  writer.synthetic("\n", "line break", [declaration], [path])
119
119
  }
120
120
  writer.synthetic("\nvoid main() {\n", "Dart generated main scaffold", [module.entryPoint], ["/entryPoint"])
121
- emitBlock(writer, module.entryPoint.body, " ", "/entryPoint/body", unreadLocals)
121
+ emitDartBlock(writer, module.entryPoint.body, " ", "/entryPoint/body", unreadLocals)
122
122
  writer.synthetic("}\n", "Dart generated main scaffold", [module.entryPoint], ["/entryPoint"])
123
123
  }
124
124
 
@@ -129,11 +129,13 @@ function emitProgram(module, writer, unreadLocals) {
129
129
  * @param {string} indent Current indentation.
130
130
  * @param {string} path Exact semantic path.
131
131
  * @param {Set<import("../semantic/types.js").LocalDeclaration>} unreadLocals Locals requiring an analyzer-only read.
132
+ * @param {string} [printTarget] Target-owned output function spelling.
133
+ * @param {boolean} [multilinePrint] Whether target plumbing requires trailing-comma multiline calls.
132
134
  * @returns {void}
133
135
  */
134
- function emitBlock(writer, block, indent, path, unreadLocals) {
136
+ export function emitDartBlock(writer, block, indent, path, unreadLocals, printTarget = "print", multilinePrint = false) {
135
137
  block.statements.forEach((statement, index) =>
136
- emitStatement(writer, statement, indent, `${path}/statements/${index}`, unreadLocals))
138
+ emitStatement(writer, statement, indent, `${path}/statements/${index}`, unreadLocals, printTarget, multilinePrint))
137
139
  }
138
140
 
139
141
  /**
@@ -143,9 +145,11 @@ function emitBlock(writer, block, indent, path, unreadLocals) {
143
145
  * @param {string} indent Current indentation.
144
146
  * @param {string} path Exact semantic path.
145
147
  * @param {Set<import("../semantic/types.js").LocalDeclaration>} unreadLocals Locals requiring an analyzer-only read.
148
+ * @param {string} printTarget Target-owned output function spelling.
149
+ * @param {boolean} multilinePrint Whether target plumbing requires trailing-comma multiline calls.
146
150
  * @returns {void}
147
151
  */
148
- function emitStatement(writer, statement, indent, path, unreadLocals) {
152
+ function emitStatement(writer, statement, indent, path, unreadLocals, printTarget, multilinePrint) {
149
153
  writer.synthetic(indent, "indentation", [statement], [path])
150
154
  if (statement.kind == "LocalDeclaration") {
151
155
  if (!statement.mutable) writer.mapped("final", {mappingKind: "anchor", node: statement, path})
@@ -181,7 +185,7 @@ function emitStatement(writer, statement, indent, path, unreadLocals) {
181
185
  writer.synthetic("\n", "line break", [statement], [path])
182
186
  return
183
187
  }
184
- if (statement.kind == "IfStatement") return emitIf(writer, statement, indent, path, unreadLocals)
188
+ if (statement.kind == "IfStatement") return emitIf(writer, statement, indent, path, unreadLocals, printTarget, multilinePrint)
185
189
  if (statement.kind == "ReturnStatement") {
186
190
  writer.mapped("return", {mappingKind: "anchor", node: statement, path})
187
191
  if (statement.expression) {
@@ -193,10 +197,15 @@ function emitStatement(writer, statement, indent, path, unreadLocals) {
193
197
  return
194
198
  }
195
199
  if (statement.kind == "PrintStatement") {
196
- writer.mapped("print", {mappingKind: "anchor", node: statement, path})
197
- writer.mapped("(", {mappingKind: "anchor", node: statement, path})
200
+ const expandedPrint = multilinePrint && writer.column - 1 + printTarget.length +
201
+ flatDartExpression(writer, statement.expression).length + 3 > 80
202
+
203
+ if (printTarget == "print") {
204
+ writer.mapped(printTarget, {mappingKind: "anchor", name: "print", node: statement, path, role: "callee"})
205
+ } else writer.synthetic(printTarget, "Dart print plumbing", [statement], [path])
206
+ writer.synthetic(`(${expandedPrint ? `\n${indent} ` : ""}`, "Dart print plumbing", [statement], [path])
198
207
  emitExpression(writer, statement.expression, `${path}/expression`, "dart", identity)
199
- writer.mapped(");", {mappingKind: "anchor", node: statement, path})
208
+ writer.synthetic(expandedPrint ? `,\n${indent});` : ");", "Dart print plumbing", [statement], [path])
200
209
  writer.synthetic("\n", "line break", [statement], [path])
201
210
  return
202
211
  }
@@ -216,23 +225,27 @@ function emitStatement(writer, statement, indent, path, unreadLocals) {
216
225
  * @param {string} indent Current indentation.
217
226
  * @param {string} path Exact semantic path.
218
227
  * @param {Set<import("../semantic/types.js").LocalDeclaration>} unreadLocals Locals requiring an analyzer-only read.
228
+ * @param {string} printTarget Target-owned output function spelling.
229
+ * @param {boolean} multilinePrint Whether target plumbing requires trailing-comma multiline calls.
219
230
  * @returns {void}
220
231
  */
221
- function emitIf(writer, statement, indent, path, unreadLocals) {
232
+ function emitIf(writer, statement, indent, path, unreadLocals, printTarget, multilinePrint) {
222
233
  writer.mapped("if", {mappingKind: "anchor", node: statement, path})
223
234
  writer.synthetic(" (", "Dart conditional scaffold", [statement], [path])
224
235
  emitExpression(writer, statement.condition, `${path}/condition`, "dart", identity)
225
236
  writer.synthetic(") ", "Dart conditional scaffold", [statement], [path])
226
237
  writer.mapped("{", {mappingKind: "anchor", node: statement.consequent, path: `${path}/consequent`})
227
238
  writer.synthetic("\n", "line break", [statement], [path])
228
- emitBlock(writer, statement.consequent, `${indent} `, `${path}/consequent`, unreadLocals)
239
+ emitDartBlock(writer, statement.consequent, `${indent} `, `${path}/consequent`, unreadLocals, printTarget,
240
+ multilinePrint)
229
241
  writer.synthetic(indent, "indentation", [statement], [path])
230
242
  writer.mapped("}", {mappingKind: "anchor", node: statement.consequent, path: `${path}/consequent`})
231
243
  if (statement.alternate) {
232
244
  writer.synthetic(" else ", "Dart alternate scaffold", [statement], [path])
233
245
  writer.mapped("{", {mappingKind: "anchor", node: statement.alternate, path: `${path}/alternate`})
234
246
  writer.synthetic("\n", "line break", [statement], [path])
235
- emitBlock(writer, statement.alternate, `${indent} `, `${path}/alternate`, unreadLocals)
247
+ emitDartBlock(writer, statement.alternate, `${indent} `, `${path}/alternate`, unreadLocals, printTarget,
248
+ multilinePrint)
236
249
  writer.synthetic(indent, "indentation", [statement], [path])
237
250
  writer.mapped("}", {mappingKind: "anchor", node: statement.alternate, path: `${path}/alternate`})
238
251
  }
@@ -244,7 +257,7 @@ function emitIf(writer, statement, indent, path, unreadLocals) {
244
257
  * @param {import("../semantic/types.js").SemanticModule} module Validated semantic module.
245
258
  * @returns {Set<import("../semantic/types.js").LocalDeclaration>} Unread declaration identities.
246
259
  */
247
- function findUnreadLocals(module) {
260
+ export function findUnreadDartLocals(module) {
248
261
  /** @type {Set<import("../semantic/types.js").LocalDeclaration>} */
249
262
  const unread = new Set()
250
263