From fcba27cd7218b0fdf5056a1b9715638a54b5dd4e Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sun, 5 Jul 2020 15:22:40 +0300
Subject: [PATCH 01/40] Tools to 0.5.1

---
 build.gradle.kts                                              | 4 ++--
 .../kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/build.gradle.kts b/build.gradle.kts
index ac454902..c3f71631 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,6 +1,5 @@
-
 plugins {
-    val toolsVersion = "0.5.0"
+    val toolsVersion = "0.5.1"
     id("scientifik.mpp") version toolsVersion apply false
     id("scientifik.jvm") version toolsVersion apply false
     id("scientifik.publish") version toolsVersion apply false
@@ -11,6 +10,7 @@ val dataforgeVersion by extra("0.1.8")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
+val spaceRepo by extra("https://maven.jetbrains.space/mipt-npm/p/df/maven")
 
 allprojects {
     group = "hep.dataforge"
diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
index 0fffdb7e..b6f4cb50 100644
--- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
+++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
@@ -18,7 +18,7 @@ class FrontMatterEnvelopeFormat(
 ) : EnvelopeFormat {
 
     override fun Input.readPartial(): PartialEnvelope {
-        var line: String = ""
+        var line = ""
         var offset = 0u
         do {
             line = readUtf8Line() //?: error("Input does not contain front matter separator")
@@ -45,7 +45,7 @@ class FrontMatterEnvelopeFormat(
     }
 
     override fun Input.readObject(): Envelope {
-        var line: String = ""
+        var line = ""
         do {
             line = readUtf8Line() //?: error("Input does not contain front matter separator")
         } while (!line.startsWith(SEPARATOR))

From 8529c725e712ee16c77509c1ecb31abe6f547c45 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Mon, 6 Jul 2020 15:02:04 +0300
Subject: [PATCH 02/40] Add more number delegates for read-only items.

---
 .../kotlin/hep/dataforge/meta/Configurable.kt |  1 +
 .../kotlin/hep/dataforge/meta/ItemDelegate.kt | 24 +++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
index 794292b9..0f880110 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
@@ -56,6 +56,7 @@ interface Configurable : Described, MutableItemProvider {
 /**
  * Reset the property to its default value
  */
+@Deprecated("To be removed since unused", ReplaceWith("setItem(name, null)"))
 fun Configurable.resetProperty(name: Name) {
     setItem(name, null)
 }
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
index aa2dec23..b710735e 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
@@ -41,6 +41,18 @@ fun ItemProvider.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> =
 fun ItemProvider.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> =
     item(key).convert(MetaConverter.number)
 
+fun ItemProvider.double(key: Name? = null): ReadOnlyProperty<Any?, Double?> =
+    item(key).convert(MetaConverter.double)
+
+fun ItemProvider.float(key: Name? = null): ReadOnlyProperty<Any?, Float?> =
+    item(key).convert(MetaConverter.float)
+
+fun ItemProvider.int(key: Name? = null): ReadOnlyProperty<Any?, Int?> =
+    item(key).convert(MetaConverter.int)
+
+fun ItemProvider.long(key: Name? = null): ReadOnlyProperty<Any?, Long?> =
+    item(key).convert(MetaConverter.long)
+
 fun ItemProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
     item(key).convert(MetaConverter.meta)
 
@@ -53,6 +65,18 @@ fun ItemProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<
 fun ItemProvider.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> =
     item(key).convert(MetaConverter.number) { default }
 
+fun ItemProvider.double(default: Double, key: Name? = null): ReadOnlyProperty<Any?, Double> =
+    item(key).convert(MetaConverter.double) { default }
+
+fun ItemProvider.float(default: Float, key: Name? = null): ReadOnlyProperty<Any?, Float> =
+    item(key).convert(MetaConverter.float) { default }
+
+fun ItemProvider.int(default: Int, key: Name? = null): ReadOnlyProperty<Any?, Int> =
+    item(key).convert(MetaConverter.int) { default }
+
+fun ItemProvider.long(default: Long, key: Name? = null): ReadOnlyProperty<Any?, Long> =
+    item(key).convert(MetaConverter.long) { default }
+
 inline fun <reified E : Enum<E>> ItemProvider.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> =
     item(key).convert(MetaConverter.enum()) { default }
 

From c3d4836a118d9b2a24d1eb8e2e824b6881b64f3b Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sun, 26 Jul 2020 10:23:51 +0300
Subject: [PATCH 03/40] Default error for Provider

---
 build.gradle.kts                                              | 4 ++--
 .../src/commonMain/kotlin/hep/dataforge/provider/Provider.kt  | 3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/build.gradle.kts b/build.gradle.kts
index c3f71631..93d3c926 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,12 +1,12 @@
 plugins {
-    val toolsVersion = "0.5.1"
+    val toolsVersion = "0.5.2"
     id("scientifik.mpp") version toolsVersion apply false
     id("scientifik.jvm") version toolsVersion apply false
     id("scientifik.publish") version toolsVersion apply false
     id("org.jetbrains.dokka") version "0.10.1"
 }
 
-val dataforgeVersion by extra("0.1.8")
+val dataforgeVersion by extra("0.1.9-dev")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
index b1d769e2..72484ea9 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
@@ -43,7 +43,8 @@ interface Provider {
     /**
      * A map of direct children for specific target
      */
-    fun provideTop(target: String): Map<Name, Any>
+    fun provideTop(target: String): Map<Name, Any> =
+        throw IllegalArgumentException("Target $target is not supported for $this")
 }
 
 fun Provider.provide(path: Path, targetOverride: String? = null): Any? {

From 4fde6c4a48782a038eab52051a9671ad73b87061 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sun, 26 Jul 2020 15:00:03 +0300
Subject: [PATCH 04/40] Replace missing query by null in NameToken

---
 .../hep/dataforge/io/MetaSerializerTest.kt    |  6 +++---
 .../kotlin/hep/dataforge/meta/Configurable.kt |  2 +-
 .../kotlin/hep/dataforge/meta/ItemDelegate.kt |  2 +-
 .../kotlin/hep/dataforge/meta/JsonMeta.kt     | 10 +++++++---
 .../hep/dataforge/meta/MutableItemDelegate.kt | 15 +-------------
 .../kotlin/hep/dataforge/meta/MutableMeta.kt  |  2 +-
 .../kotlin/hep/dataforge/meta/metaMatcher.kt  | 20 ++++++++++---------
 .../kotlin/hep/dataforge/names/Name.kt        | 12 ++++++-----
 .../dataforge/tables/io/textTableEnvelope.kt  |  2 +-
 9 files changed, 33 insertions(+), 38 deletions(-)

diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
index dc8e5016..ef301710 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
@@ -21,7 +21,7 @@ class MetaSerializerTest {
     fun testMetaSerialization() {
         val string = JSON_PRETTY.stringify(MetaSerializer, meta)
         val restored = JSON_PLAIN.parse(MetaSerializer, string)
-        assertEquals(restored, meta)
+        assertEquals(meta, restored)
     }
 
     @Test
@@ -29,7 +29,7 @@ class MetaSerializerTest {
         val bytes = Cbor.dump(MetaSerializer, meta)
         println(bytes.contentToString())
         val restored = Cbor.load(MetaSerializer, bytes)
-        assertEquals(restored, meta)
+        assertEquals(meta, restored)
     }
 
     @Test
@@ -37,7 +37,7 @@ class MetaSerializerTest {
         val name = "a.b.c".toName()
         val string = JSON_PRETTY.stringify(Name.serializer(), name)
         val restored = JSON_PLAIN.parse(Name.serializer(), string)
-        assertEquals(restored, name)
+        assertEquals(name, restored)
     }
 
     @Test
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
index 0f880110..a984b897 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
@@ -26,7 +26,7 @@ interface Configurable : Described, MutableItemProvider {
     fun getDefaultItem(name: Name): MetaItem<*>? = null
 
     /**
-     * Check if property with given [name] could be assigned to [value]
+     * Check if property with given [name] could be assigned to [item]
      */
     fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
         val descriptor = descriptor?.get(name)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
index b710735e..cffedd82 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
@@ -8,7 +8,7 @@ import kotlin.properties.ReadOnlyProperty
 import kotlin.reflect.KProperty
 
 /* Meta delegates */
-
+//TODO to be replaced in 1.4 by interfaces
 open class ItemDelegate(
     open val owner: ItemProvider,
     val key: Name? = null,
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
index 221b040d..debe3080 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
@@ -52,7 +52,7 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
     fun addElement(key: String) {
         val itemDescriptor = descriptor?.items?.get(key)
         val jsonKey = key.toJsonKey(itemDescriptor)
-        val items: Map<String, MetaItem<*>> = getIndexed(key)
+        val items: Map<String?, MetaItem<*>> = getIndexed(key)
         when (items.size) {
             0 -> {
                 //do nothing
@@ -94,7 +94,11 @@ fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
                 true -> True
                 false -> False
                 is Number -> NumberValue(body as Number)
-                else -> StringValue(content)
+                else -> if (isString) {
+                    StringValue(content)
+                } else {
+                    content.parseValue()
+                }
             }
         }
     }
@@ -174,7 +178,7 @@ class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : M
 
     override val items: Map<NameToken, MetaItem<JsonMeta>> by lazy(::buildItems)
 
-    companion object{
+    companion object {
         /**
          * A key representing top-level json array of nodes, which could not be directly represented by a meta node
          */
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
index 3885b809..163408e1 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
@@ -71,6 +71,7 @@ inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProp
     item(key).convert(reader = { it?.let { it.node as M } }, writer = { it?.let { MetaItem.NodeItem(it) } })
 
 
+@Deprecated("To be replaced by a converter")
 fun <T> MutableItemProvider.item(
     default: T? = null,
     key: Name? = null,
@@ -85,20 +86,6 @@ fun <T> MutableItemProvider.item(
 fun Configurable.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
     item(key).convert(MetaConverter.value)
 
-fun <T> MutableItemProvider.value(
-    default: T? = null,
-    key: Name? = null,
-    writer: (T) -> Value? = { Value.of(it) },
-    reader: (Value?) -> T
-): ReadWriteProperty<Any?, T> = MutableItemDelegate(
-    this,
-    key,
-    default?.let { MetaItem.of(it) }
-).convert(
-    reader = { reader(it.value) },
-    writer = { value -> writer(value)?.let { MetaItem.ValueItem(it) } }
-)
-
 /* Number delegates*/
 
 fun MutableItemProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> =
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
index 03245b00..13965505 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
@@ -160,7 +160,7 @@ operator fun MutableMeta<*>.set(name: String, metas: Iterable<Meta>): Unit = set
 fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
     require(!name.isEmpty()) { "Name could not be empty for append operation" }
     val newIndex = name.last()!!.index
-    if (newIndex.isNotEmpty()) {
+    if (newIndex != null) {
         set(name, value)
     } else {
         val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.max() ?: -1) + 1
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt
index f2f747db..26dc009c 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt
@@ -7,23 +7,25 @@ import hep.dataforge.names.toName
  * Get all items matching given name. The index of the last element, if present is used as a [Regex],
  * against which indexes of elements are matched.
  */
-fun Meta.getIndexed(name: Name): Map<String, MetaItem<*>> {
+fun Meta.getIndexed(name: Name): Map<String?, MetaItem<*>> {
     val root = when (name.length) {
         0 -> error("Can't use empty name for 'getIndexed'")
         1 -> this
-        else -> this[name.cutLast()].node
+        else -> this[name.cutLast()].node ?: return emptyMap()
     }
 
     val (body, index) = name.last()!!
-    val regex = index.toRegex()
-
-    return root?.items
-        ?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) }
-        ?.mapKeys { it.key.index }
-        ?: emptyMap()
+    return if (index == null) {
+        root.items.filter { it.key.body == body }.mapKeys { it.key.index }
+    } else {
+        val regex = index.toRegex()
+        root.items
+            .filter { it.key.body == body && (regex.matches(it.key.index ?: "")) }
+            .mapKeys { it.key.index }
+    }
 }
 
-fun Meta.getIndexed(name: String): Map<String, MetaItem<*>> = this@getIndexed.getIndexed(name.toName())
+fun Meta.getIndexed(name: String): Map<String?, MetaItem<*>> = this@getIndexed.getIndexed(name.toName())
 
 /**
  * Get all items matching given name.
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
index b3f8231a..5ed2ff81 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
@@ -78,7 +78,7 @@ class Name(val tokens: List<NameToken>) {
  * A name token could have appendix in square brackets called *index*
  */
 @Serializable
-data class NameToken(val body: String, val index: String = "") {
+data class NameToken(val body: String, val index: String? = null) {
 
     init {
         if (body.isEmpty()) error("Syntax error: Name token body is empty")
@@ -96,7 +96,7 @@ data class NameToken(val body: String, val index: String = "") {
         body.escape()
     }
 
-    fun hasIndex() = index.isNotEmpty()
+    fun hasIndex() = index != null
 
     @Serializer(NameToken::class)
     companion object : KSerializer<NameToken> {
@@ -150,7 +150,8 @@ fun String.toName(): Name {
                 }
                 else -> when (it) {
                     '.' -> {
-                        yield(NameToken(bodyBuilder.toString(), queryBuilder.toString()))
+                        val query = if(queryBuilder.isEmpty()) null else queryBuilder.toString()
+                        yield(NameToken(bodyBuilder.toString(), query))
                         bodyBuilder = StringBuilder()
                         queryBuilder = StringBuilder()
                     }
@@ -163,7 +164,8 @@ fun String.toName(): Name {
                 }
             }
         }
-        yield(NameToken(bodyBuilder.toString(), queryBuilder.toString()))
+        val query = if(queryBuilder.isEmpty()) null else queryBuilder.toString()
+        yield(NameToken(bodyBuilder.toString(), query))
     }
     return Name(tokens.toList())
 }
@@ -206,7 +208,7 @@ fun Name.withIndex(index: String): Name {
 /**
  * Fast [String]-based accessor for item map
  */
-operator fun <T> Map<NameToken, T>.get(body: String, query: String = ""): T? = get(NameToken(body, query))
+operator fun <T> Map<NameToken, T>.get(body: String, query: String? = null): T? = get(NameToken(body, query))
 
 operator fun <T> Map<Name, T>.get(name: String) = get(name.toName())
 operator fun <T> MutableMap<Name, T>.set(name: String, value: T) = set(name.toName(), value)
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt
index e634346c..10c9b3fc 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt
@@ -34,7 +34,7 @@ suspend fun Table<Value>.wrap(): Envelope = Envelope {
 @ExperimentalIoApi
 fun TextRows.Companion.readEnvelope(envelope: Envelope): TextRows {
     val header = envelope.meta.getIndexed("column")
-        .entries.sortedBy { it.key.toInt() }
+        .entries.sortedBy { it.key?.toInt() }
         .map { (_, item) ->
             SimpleColumnHeader(item.node["name"].string!!, Value::class, item.node["meta"].node ?: Meta.EMPTY)
         }

From b72f73f75bb819ef6a8dcf6f4afca0ba54b767d5 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sun, 26 Jul 2020 17:34:35 +0300
Subject: [PATCH 05/40] Remove needless item delegate

---
 .../kotlin/hep/dataforge/meta/Meta.kt         |  5 +-
 .../hep/dataforge/meta/MutableItemDelegate.kt | 63 +++++++++----------
 2 files changed, 33 insertions(+), 35 deletions(-)

diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
index a89d79c9..d01e9786 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
@@ -77,6 +77,9 @@ sealed class MetaItem<out M : Meta> {
     }
 }
 
+fun Value.asMetaItem() = ValueItem(this)
+fun <M:Meta> M.asMetaItem() = NodeItem(this)
+
 /**
  * The object that could be represented as [Meta]. Meta provided by [toMeta] method should fully represent object state.
  * Meaning that two states with the same meta are equal.
@@ -265,7 +268,7 @@ inline fun <reified E : Enum<E>> MetaItem<*>?.enum(): E? = if (this is ValueItem
     string?.let { enumValueOf<E>(it) }
 }
 
-val MetaItem<*>?.stringList get() = value?.list?.map { it.string } ?: emptyList()
+val MetaItem<*>.stringList get() = value?.list?.map { it.string }
 
 val <M : Meta> MetaItem<M>?.node: M?
     get() = when (this) {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
index 163408e1..189b9e0f 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
@@ -5,7 +5,8 @@ import hep.dataforge.names.Name
 import hep.dataforge.names.asName
 import hep.dataforge.values.DoubleArrayValue
 import hep.dataforge.values.Value
-import hep.dataforge.values.stringList
+import hep.dataforge.values.asValue
+import hep.dataforge.values.doubleArray
 import kotlin.properties.ReadWriteProperty
 import kotlin.reflect.KProperty
 
@@ -71,18 +72,6 @@ inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProp
     item(key).convert(reader = { it?.let { it.node as M } }, writer = { it?.let { MetaItem.NodeItem(it) } })
 
 
-@Deprecated("To be replaced by a converter")
-fun <T> MutableItemProvider.item(
-    default: T? = null,
-    key: Name? = null,
-    writer: (T) -> MetaItem<*>? = { MetaItem.of(it) },
-    reader: (MetaItem<*>?) -> T
-): ReadWriteProperty<Any?, T> = MutableItemDelegate(
-    this,
-    key,
-    default?.let { MetaItem.of(it) }
-).convert(reader = reader, writer = writer)
-
 fun Configurable.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
     item(key).convert(MetaConverter.value)
 
@@ -119,33 +108,39 @@ fun MutableItemProvider.float(default: Float, key: Name? = null): ReadWritePrope
 /*
  * Extra delegates for special cases
  */
-fun MutableItemProvider.stringList(vararg strings: String, key: Name? = null): ReadWriteProperty<Any?, List<String>> =
-    item(listOf(*strings), key) {
-        it?.value?.stringList ?: emptyList()
-    }
-
-fun MutableItemProvider.stringListOrNull(
-    vararg strings: String,
+fun MutableItemProvider.stringList(
+    vararg default: String,
     key: Name? = null
-): ReadWriteProperty<Any?, List<String>?> =
-    item(listOf(*strings), key) {
-        it?.value?.stringList
-    }
+): ReadWriteProperty<Any?, List<String>> = item(key).convert(
+    reader = { it?.stringList ?: listOf(*default) },
+    writer = { it.map { str -> str.asValue() }.asValue().asMetaItem() }
+)
 
-fun MutableItemProvider.numberList(vararg numbers: Number, key: Name? = null): ReadWriteProperty<Any?, List<Number>> =
-    item(listOf(*numbers), key) { item ->
-        item?.value?.list?.map { it.number } ?: emptyList()
-    }
+fun MutableItemProvider.stringList(
+    key: Name? = null
+): ReadWriteProperty<Any?, List<String>?> = item(key).convert(
+    reader = {  it?.stringList },
+    writer = { it?.map { str -> str.asValue() }?.asValue()?.asMetaItem() }
+)
+
+fun MutableItemProvider.numberList(
+    vararg default: Number,
+    key: Name? = null
+): ReadWriteProperty<Any?, List<Number>> = item(key).convert(
+    reader = { it?.value?.list?.map { value -> value.number } ?: listOf(*default) },
+    writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() }
+)
 
 /**
  * A special delegate for double arrays
  */
-fun MutableItemProvider.doubleArray(vararg doubles: Double, key: Name? = null): ReadWriteProperty<Any?, DoubleArray> =
-    item(doubleArrayOf(*doubles), key) {
-        (it.value as? DoubleArrayValue)?.value
-            ?: it?.value?.list?.map { value -> value.number.toDouble() }?.toDoubleArray()
-            ?: doubleArrayOf()
-    }
+fun MutableItemProvider.doubleArray(
+    vararg default: Double,
+    key: Name? = null
+): ReadWriteProperty<Any?, DoubleArray> =item(key).convert(
+    reader = { it?.value?.doubleArray ?: doubleArrayOf(*default) },
+    writer = { DoubleArrayValue(it).asMetaItem() }
+)
 
 fun <T> MutableItemProvider.listValue(
     key: Name? = null,

From 34110f6be15c55c4b0357f86fc25aa10ad0512e5 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sun, 26 Jul 2020 17:35:44 +0300
Subject: [PATCH 06/40] Remove function clients and servers

---
 .../kotlin/hep/dataforge/io/Responder.kt      | 13 +++
 .../dataforge/io/functions/FunctionServer.kt  | 75 --------------
 .../io/functions/RemoteFunctionClient.kt      | 98 -------------------
 .../io/functions/RemoteFunctionServer.kt      | 58 -----------
 .../kotlin/hep/dataforge/io/functionsJVM.kt   | 28 ------
 5 files changed, 13 insertions(+), 259 deletions(-)
 delete mode 100644 dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/FunctionServer.kt
 delete mode 100644 dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionClient.kt
 delete mode 100644 dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionServer.kt
 delete mode 100644 dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/functionsJVM.kt

diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt
index e3545782..c0214e7b 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt
@@ -1,8 +1,21 @@
 package hep.dataforge.io
 
+import hep.dataforge.meta.DFExperimental
+
+/**
+ * An object that could respond to external messages asynchronously
+ */
 interface Responder {
     /**
      * Send a request and wait for response for this specific request
      */
     suspend fun respond(request: Envelope): Envelope
+}
+
+/**
+ * A fire-and-forget consumer of messages
+ */
+@DFExperimental
+interface Consumer {
+    fun consume(message: Envelope): Unit
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/FunctionServer.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/FunctionServer.kt
deleted file mode 100644
index 2eca605c..00000000
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/FunctionServer.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package hep.dataforge.io.functions
-
-import hep.dataforge.context.ContextAware
-import hep.dataforge.io.IOFormat
-import hep.dataforge.io.IOPlugin
-import hep.dataforge.meta.Meta
-import hep.dataforge.meta.get
-import hep.dataforge.names.asName
-import hep.dataforge.names.plus
-import kotlin.reflect.KClass
-
-
-/**
- * A server that could produce asynchronous function values
- */
-interface FunctionServer : ContextAware {
-    /**
-     * Call a function with given name and descriptor
-     */
-    suspend fun <T : Any, R : Any> call(meta: Meta, arg: T, inputType: KClass<out T>, outputType: KClass<out R>): R
-
-    suspend fun <T : Any, R : Any> callMany(
-        meta: Meta,
-        arg: List<T>,
-        inputType: KClass<out T>,
-        outputType: KClass<out R>
-    ): List<R> = List(arg.size) {
-        call<T, R>(meta, arg[it], inputType, outputType)
-    }
-
-    /**
-     * Get a generic suspended function with given name and descriptor
-     */
-    fun <T : Any, R : Any> function(
-        meta: Meta,
-        inputType: KClass<out T>,
-        outputType: KClass<out R>
-    ): (suspend (T) -> R) = { call(meta, it, inputType, outputType) }
-
-    companion object {
-        const val FUNCTION_NAME_KEY = "function"
-        val FORMAT_KEY = "format".asName()
-        val INPUT_FORMAT_KEY = FORMAT_KEY + "input"
-        val OUTPUT_FORMAT_KEY = FORMAT_KEY + "output"
-    }
-}
-
-suspend inline fun <reified T : Any, reified R : Any> FunctionServer.call(meta: Meta, arg: T) =
-    call(meta, arg, T::class, R::class)
-
-suspend inline fun <reified T : Any, reified R : Any> FunctionServer.callMany(meta: Meta, arg: List<T>) =
-    callMany(meta, arg, T::class, R::class)
-
-inline fun <reified T : Any, reified R : Any> FunctionServer.function(meta: Meta) =
-    function(meta, T::class, R::class)
-
-fun <T : Any> IOPlugin.getInputFormat(meta: Meta, type: KClass<out T>): IOFormat<T> {
-    return meta[FunctionServer.INPUT_FORMAT_KEY]?.let {
-        resolveIOFormat<T>(it, type)
-    } ?: error("Input format not resolved")
-}
-
-fun <R : Any> IOPlugin.getOutputFormat(meta: Meta, type: KClass<out R>): IOFormat<R> {
-    return meta[FunctionServer.OUTPUT_FORMAT_KEY]?.let {
-        resolveIOFormat<R>(it, type)
-    } ?: error("Input format not resolved")
-}
-
-inline fun <reified T : Any> IOPlugin.getInputFormat(meta: Meta): IOFormat<T> =
-    getInputFormat(meta, T::class)
-
-inline fun <reified R : Any> IOPlugin.getOutputFormat(meta: Meta): IOFormat<R> =
-    getOutputFormat(meta, R::class)
-
-
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionClient.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionClient.kt
deleted file mode 100644
index 7c294891..00000000
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionClient.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-package hep.dataforge.io.functions
-
-import hep.dataforge.context.Context
-import hep.dataforge.context.ContextAware
-import hep.dataforge.io.*
-import hep.dataforge.meta.Meta
-import hep.dataforge.meta.get
-import hep.dataforge.meta.int
-import kotlin.reflect.KClass
-
-class RemoteFunctionClient(override val context: Context, val responder: Responder) : FunctionServer, ContextAware {
-
-    private fun <T : Any> IOPlugin.encodeOne(
-        meta: Meta,
-        value: T,
-        valueType: KClass<out T> = value::class
-    ): Envelope = Envelope.invoke {
-        meta(meta)
-        type = REQUEST_TYPE
-        data {
-            val inputFormat: IOFormat<T> = getInputFormat(meta, valueType)
-            inputFormat.run {
-                writeObject(value)
-            }
-        }
-    }
-
-    private fun <T : Any> IOPlugin.encodeMany(
-        meta: Meta,
-        values: List<T>,
-        valueType: KClass<out T>
-    ): Envelope = Envelope.invoke {
-        meta(meta)
-        type = REQUEST_TYPE
-        meta {
-            SIZE_KEY put values.size
-        }
-        data {
-            val inputFormat: IOFormat<T> = getInputFormat(meta, valueType)
-            inputFormat.run {
-                values.forEach {
-                    writeObject(it)
-                }
-            }
-        }
-    }
-
-    private fun <R : Any> IOPlugin.decode(envelope: Envelope, valueType: KClass<out R>): List<R> {
-        require(envelope.type == RESPONSE_TYPE) { "Unexpected message type: ${envelope.type}" }
-        val size = envelope.meta[SIZE_KEY].int ?: 1
-
-        return if (size == 0) {
-            emptyList()
-        } else {
-            val outputFormat: IOFormat<R> = getOutputFormat(envelope.meta, valueType)
-            envelope.data?.read {
-                List<R>(size) {
-                    outputFormat.run {
-                        readObject()
-                    }
-                }
-            } ?: error("Message does not contain data")
-        }
-    }
-
-    private val plugin by lazy {
-        context.plugins.load(IOPlugin)
-    }
-
-    override suspend fun <T : Any, R : Any> call(
-        meta: Meta,
-        arg: T,
-        inputType: KClass<out T>,
-        outputType: KClass<out R>
-    ): R = plugin.run {
-        val request = encodeOne(meta, arg)
-        val response = responder.respond(request)
-        return decode<R>(response, outputType).first()
-    }
-
-    override suspend fun <T : Any, R : Any> callMany(
-        meta: Meta,
-        arg: List<T>,
-        inputType: KClass<out T>,
-        outputType: KClass<out R>
-    ): List<R> = plugin.run {
-        val request = encodeMany(meta, arg, inputType)
-        val response = responder.respond(request)
-        return decode<R>(response, outputType)
-    }
-
-    companion object {
-        const val REQUEST_TYPE = "function.request"
-        const val RESPONSE_TYPE = "function.response"
-
-        const val SIZE_KEY = "size"
-    }
-}
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionServer.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionServer.kt
deleted file mode 100644
index 8252b1d3..00000000
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionServer.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-package hep.dataforge.io.functions
-
-import hep.dataforge.context.Context
-import hep.dataforge.context.ContextAware
-import hep.dataforge.io.Envelope
-import hep.dataforge.io.IOPlugin
-import hep.dataforge.io.Responder
-import hep.dataforge.io.type
-import hep.dataforge.meta.get
-import hep.dataforge.meta.int
-
-class RemoteFunctionServer(
-    override val context: Context,
-    val functionServer: FunctionServer
-) : ContextAware, Responder {
-
-    private val plugin by lazy {
-        context.plugins.load(IOPlugin)
-    }
-
-
-    override suspend fun respond(request: Envelope): Envelope {
-        require(request.type == RemoteFunctionClient.REQUEST_TYPE) { "Unexpected message type: ${request.type}" }
-
-        val inputFormat = plugin.getInputFormat<Any>(request.meta)
-        val outputFormat = plugin.getOutputFormat<Any>(request.meta)
-
-        val size = request.meta[RemoteFunctionClient.SIZE_KEY].int ?: 1
-
-        val input = request.data?.read {
-            inputFormat.run {
-                List(size) {
-                    readObject()
-                }
-            }
-        } ?: error("Input is empty")
-
-        val output = functionServer.callMany<Any, Any>(
-            request.meta,
-            input
-        )
-
-        return Envelope.invoke {
-            meta {
-                meta(request.meta)
-            }
-            type = RemoteFunctionClient.RESPONSE_TYPE
-            data {
-                outputFormat.run {
-                    output.forEach {
-                        writeObject(it)
-                    }
-                }
-            }
-
-        }
-    }
-}
\ No newline at end of file
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/functionsJVM.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/functionsJVM.kt
deleted file mode 100644
index ccd57c55..00000000
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/functionsJVM.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package hep.dataforge.io
-
-import hep.dataforge.io.functions.FunctionServer
-import hep.dataforge.io.functions.function
-import hep.dataforge.meta.Meta
-import hep.dataforge.names.Name
-import kotlin.reflect.KClass
-import kotlin.reflect.full.isSuperclassOf
-
-
-fun IOPlugin.resolveIOFormatName(type: KClass<*>): Name {
-    return ioFormatFactories.find { it.type.isSuperclassOf(type) }?.name
-        ?: error("Can't resolve IOFormat for type $type")
-}
-
-inline fun <reified T : Any, reified R : Any> IOPlugin.generateFunctionMeta(functionName: String): Meta = Meta {
-    FunctionServer.FUNCTION_NAME_KEY put functionName
-    FunctionServer.INPUT_FORMAT_KEY put resolveIOFormatName(T::class).toString()
-    FunctionServer.OUTPUT_FORMAT_KEY put resolveIOFormatName(R::class).toString()
-}
-
-inline fun <reified T : Any, reified R : Any> FunctionServer.function(
-    functionName: String
-): (suspend (T) -> R) {
-    val plugin = context.plugins.get<IOPlugin>() ?: error("IO plugin not loaded")
-    val meta = plugin.generateFunctionMeta<T, R>(functionName)
-    return function(meta)
-}
\ No newline at end of file

From b5b0a6898e94f753b87dab9dc136d6a983fd0989 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sun, 26 Jul 2020 17:36:18 +0300
Subject: [PATCH 07/40] Add default implementation to the provider.

---
 .../commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt | 2 --
 .../src/commonMain/kotlin/hep/dataforge/provider/Provider.kt  | 4 +---
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt
index e1041935..42adce2c 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt
@@ -30,8 +30,6 @@ abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plugin {
         dependencies.add(factory)
         return PluginDependencyDelegate(factory.type)
     }
-
-    override fun provideTop(target: String): Map<Name, Any> = emptyMap()
 }
 
 fun <T : Named> Collection<T>.toMap(): Map<Name, T> = associate { it.name to it }
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
index 72484ea9..a1c2faa1 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
@@ -39,12 +39,10 @@ interface Provider {
      */
     val defaultChainTarget: String get() = ""
 
-
     /**
      * A map of direct children for specific target
      */
-    fun provideTop(target: String): Map<Name, Any> =
-        throw IllegalArgumentException("Target $target is not supported for $this")
+    fun provideTop(target: String): Map<Name, Any> = emptyMap()
 }
 
 fun Provider.provide(path: Path, targetOverride: String? = null): Any? {

From 617612bf6778c7c7d118639b46a87f396a0609e1 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sat, 15 Aug 2020 20:33:39 +0300
Subject: [PATCH 08/40] Add default implementation to the provider.

---
 CHANGELOG.md                                  | 18 ++++++++++++++++++
 build.gradle.kts                              |  3 ++-
 .../kotlin/hep/dataforge/context/Context.kt   |  6 +++++-
 .../kotlin/hep/dataforge/provider/Provider.kt | 19 +++++++++----------
 .../kotlin/hep/dataforge/provider/Types.kt    | 10 +++++-----
 5 files changed, 39 insertions(+), 17 deletions(-)
 create mode 100644 CHANGELOG.md

diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..b08d3d08
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Changelog
+
+## [Unreleased]
+### Added
+
+### Changed
+- Empty query in Name is null instead of ""
+- Provider provides an empty map instead of error by default
+
+### Deprecated
+
+### Removed
+- Functional server prototype
+
+### Fixed
+- Global context CoroutineScope resolution
+
+### Security
diff --git a/build.gradle.kts b/build.gradle.kts
index 93d3c926..06cfe9e2 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -4,9 +4,10 @@ plugins {
     id("scientifik.jvm") version toolsVersion apply false
     id("scientifik.publish") version toolsVersion apply false
     id("org.jetbrains.dokka") version "0.10.1"
+    id("org.jetbrains.changelog") version "0.4.0"
 }
 
-val dataforgeVersion by extra("0.1.9-dev")
+val dataforgeVersion by extra("0.1.9-dev-1")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
index bf901991..8bcdff57 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
@@ -8,6 +8,7 @@ import hep.dataforge.provider.Provider
 import hep.dataforge.provider.top
 import hep.dataforge.values.Value
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.SupervisorJob
 import mu.KLogger
@@ -92,7 +93,7 @@ open class Context(
         config.action()
     }
 
-    override val coroutineContext: CoroutineContext by lazy {
+    open override val coroutineContext: CoroutineContext by lazy {
         (parent ?: Global).coroutineContext.let { parenContext ->
             parenContext + SupervisorJob(parenContext[Job])
         }
@@ -130,6 +131,9 @@ inline fun <reified T : Any> Context.content(target: String): Map<Name, T> =
  * A global root context. Closing [Global] terminates the framework.
  */
 object Global : Context("GLOBAL".asName(), null) {
+
+    override val coroutineContext: CoroutineContext = GlobalScope.coroutineContext + SupervisorJob()
+
     /**
      * Closing all contexts
      *
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
index a1c2faa1..bea7b12c 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
@@ -16,7 +16,6 @@
 package hep.dataforge.provider
 
 import hep.dataforge.names.Name
-import hep.dataforge.names.toName
 
 /**
  * A marker utility interface for providers.
@@ -64,16 +63,16 @@ fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
 /**
  * Type checked provide
  */
-inline fun <reified T : Any> Provider.provide(path: String): T? {
-    return provide(Path.parse(path)) as? T
+inline fun <reified T : Any> Provider.provide(path: String, targetOverride: String? = null): T? {
+    return provide(Path.parse(path), targetOverride) as? T
 }
-
-inline fun <reified T : Any> Provider.provide(target: String, name: Name): T? {
-    return provide(PathToken(name, target).toPath()) as? T
-}
-
-inline fun <reified T : Any> Provider.provide(target: String, name: String): T? =
-    provide(target, name.toName())
+//
+//inline fun <reified T : Any> Provider.provide(target: String, name: Name): T? {
+//    return provide(PathToken(name, target).toPath()) as? T
+//}
+//
+//inline fun <reified T : Any> Provider.provide(target: String, name: String): T? =
+//    provide(target, name.toName())
 
 /**
  *  Typed top level content
diff --git a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
index dfe81ce0..a7c27662 100644
--- a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
+++ b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
@@ -26,11 +26,11 @@ inline fun <reified T : Any> Provider.provideByType(name: String): T? {
     val target = Types[T::class]
     return provide(target, name)
 }
-
-inline fun <reified T : Any> Provider.provideByType(name: Name): T? {
-    val target = Types[T::class]
-    return provide(target, name)
-}
+//
+//inline fun <reified T : Any> Provider.provideByType(name: Name): T? {
+//    val target = Types[T::class]
+//    return provide(target, name)
+//}
 
 inline fun <reified T : Any> Provider.top(): Map<Name, T> {
     val target = Types[T::class]

From b8d775aa30d8577e5450abe82ed6690caae4e776 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sat, 29 Aug 2020 11:45:31 +0300
Subject: [PATCH 09/40] Migration to 1.4

---
 build.gradle.kts                              | 12 +--
 dataforge-context/build.gradle.kts            | 13 ++-
 .../hep/dataforge/context/ContextBuilder.kt   |  1 -
 dataforge-data/build.gradle.kts               | 21 ++---
 dataforge-io/build.gradle.kts                 | 13 ++-
 .../dataforge-io-yaml/build.gradle.kts        |  9 +-
 .../io/yaml/FrontMatterEnvelopeFormat.kt      |  5 +-
 .../kotlin/hep/dataforge/io/Envelope.kt       |  2 +-
 .../hep/dataforge/io/EnvelopeBuilder.kt       | 30 ++++---
 .../kotlin/hep/dataforge/io/JsonMetaFormat.kt | 11 ++-
 .../kotlin/hep/dataforge/io/ioMisc.kt         |  2 +-
 .../kotlin/hep/dataforge/io/MetaFormatTest.kt | 32 ++++---
 .../hep/dataforge/io/MetaSerializerTest.kt    | 12 +--
 .../hep/dataforge/io/tcp/EnvelopeClient.kt    | 10 ++-
 .../hep/dataforge/io/tcp/EnvelopeServer.kt    | 11 +--
 dataforge-meta/build.gradle.kts               |  8 +-
 .../kotlin/hep/dataforge/meta/Config.kt       | 16 +++-
 .../kotlin/hep/dataforge/meta/JsonMeta.kt     | 23 ++---
 .../kotlin/hep/dataforge/meta/Meta.kt         |  9 +-
 .../hep/dataforge/meta/MetaSerializer.kt      | 20 +++--
 .../kotlin/hep/dataforge/meta/MutableMeta.kt  |  2 +-
 .../hep/dataforge/meta/serializationUtils.kt  | 50 ++++++-----
 .../kotlin/hep/dataforge/names/Name.kt        | 13 ++-
 .../hep/dataforge/values/ValueSerializer.kt   | 17 ++--
 .../kotlin/hep/dataforge/meta/JsonMetaTest.kt | 51 ++++++-----
 .../kotlin/hep/dataforge/meta/DynamicMeta.kt  |  4 +-
 dataforge-output/build.gradle.kts             |  2 +-
 .../dataforge-output-html/build.gradle.kts    | 16 +---
 dataforge-scripting/build.gradle.kts          |  5 +-
 dataforge-tables/build.gradle.kts             |  2 +-
 dataforge-workspace/build.gradle.kts          |  4 +-
 gradle/artifactory.gradle                     | 31 -------
 gradle/bintray.gradle                         | 85 -------------------
 settings.gradle.kts                           | 14 ++-
 34 files changed, 222 insertions(+), 334 deletions(-)
 delete mode 100644 gradle/artifactory.gradle
 delete mode 100644 gradle/bintray.gradle

diff --git a/build.gradle.kts b/build.gradle.kts
index 06cfe9e2..129a3adc 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,9 +1,9 @@
 plugins {
-    val toolsVersion = "0.5.2"
-    id("scientifik.mpp") version toolsVersion apply false
-    id("scientifik.jvm") version toolsVersion apply false
-    id("scientifik.publish") version toolsVersion apply false
-    id("org.jetbrains.dokka") version "0.10.1"
+    val toolsVersion = "0.6.0"
+    id("kscience.mpp") version toolsVersion apply false
+    id("kscience.jvm") version toolsVersion apply false
+    id("kscience.publish") version toolsVersion apply false
+    id("org.jetbrains.dokka") version "1.4.0-rc"
     id("org.jetbrains.changelog") version "0.4.0"
 }
 
@@ -23,6 +23,6 @@ allprojects {
 }
 
 subprojects {
-    apply(plugin = "scientifik.publish")
+    apply(plugin = "kscience.publish")
     apply(plugin = "org.jetbrains.dokka")
 }
\ No newline at end of file
diff --git a/dataforge-context/build.gradle.kts b/dataforge-context/build.gradle.kts
index c5b41223..90a7a7a3 100644
--- a/dataforge-context/build.gradle.kts
+++ b/dataforge-context/build.gradle.kts
@@ -1,32 +1,29 @@
-import scientifik.useCoroutines
-
 plugins {
-    id("scientifik.mpp")
+    id("kscience.mpp")
 }
 
 description = "Context and provider definitions"
 
-
-useCoroutines()
+kscience{
+    useCoroutines()
+}
 
 kotlin {
     sourceSets {
         val commonMain by getting {
             dependencies {
                 api(project(":dataforge-meta"))
-                api("io.github.microutils:kotlin-logging-common:1.7.9")
+                api("io.github.microutils:kotlin-logging:1.9.0")
             }
         }
         val jvmMain by getting {
             dependencies {
                 api(kotlin("reflect"))
-                api("io.github.microutils:kotlin-logging:1.7.9")
                 api("ch.qos.logback:logback-classic:1.2.3")
             }
         }
         val jsMain by getting {
             dependencies {
-                api("io.github.microutils:kotlin-logging-js:1.7.9")
             }
         }
     }
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
index 1f267c37..70187191 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
@@ -3,7 +3,6 @@ package hep.dataforge.context
 import hep.dataforge.meta.DFBuilder
 import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaBuilder
-import hep.dataforge.meta.buildMeta
 import hep.dataforge.names.toName
 
 /**
diff --git a/dataforge-data/build.gradle.kts b/dataforge-data/build.gradle.kts
index 793f551b..6afb4230 100644
--- a/dataforge-data/build.gradle.kts
+++ b/dataforge-data/build.gradle.kts
@@ -1,29 +1,22 @@
 plugins {
-    id("scientifik.mpp")
+    id("kscience.mpp")
 }
 
-val coroutinesVersion: String = Scientifik.coroutinesVersion
+kscience{
+    useCoroutines()
+}
 
 kotlin {
     sourceSets {
-        val commonMain by getting{
+        commonMain{
             dependencies {
                 api(project(":dataforge-meta"))
-                api("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutinesVersion")
             }
         }
-
-        val jvmMain by getting{
-            dependencies {
-                api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
+        jvmMain{
+            dependencies{
                 api(kotlin("reflect"))
             }
         }
-
-        val jsMain by getting{
-            dependencies {
-                api("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutinesVersion")
-            }
-        }
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/build.gradle.kts b/dataforge-io/build.gradle.kts
index 15439cd4..d7d0d8fb 100644
--- a/dataforge-io/build.gradle.kts
+++ b/dataforge-io/build.gradle.kts
@@ -1,17 +1,16 @@
-import scientifik.DependencySourceSet.TEST
-import scientifik.useSerialization
-
 plugins {
-    id("scientifik.mpp")
+    id("kscience.mpp")
 }
 
 description = "IO module"
 
-useSerialization(sourceSet = TEST){
-    cbor()
+kscience {
+    useSerialization(sourceSet = ru.mipt.npm.gradle.DependencySourceSet.TEST) {
+        cbor()
+    }
 }
 
-val ioVersion by rootProject.extra("0.2.0-npm-dev-7")
+val ioVersion by rootProject.extra("0.2.0-npm-dev-10")
 
 kotlin {
     sourceSets {
diff --git a/dataforge-io/dataforge-io-yaml/build.gradle.kts b/dataforge-io/dataforge-io-yaml/build.gradle.kts
index f29bff4a..be1cace6 100644
--- a/dataforge-io/dataforge-io-yaml/build.gradle.kts
+++ b/dataforge-io/dataforge-io-yaml/build.gradle.kts
@@ -1,13 +1,14 @@
-import scientifik.useSerialization
 
 plugins {
-    id("scientifik.jvm")
+    id("kscience.jvm")
 }
 
 description = "YAML meta IO"
 
-useSerialization{
-    yaml()
+kscience {
+    useSerialization {
+        yaml()
+    }
 }
 
 dependencies {
diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
index b6f4cb50..bc334de5 100644
--- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
+++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
@@ -9,7 +9,6 @@ import hep.dataforge.meta.Meta
 import kotlinx.io.*
 import kotlinx.io.text.readUtf8Line
 import kotlinx.io.text.writeUtf8String
-import kotlinx.serialization.toUtf8Bytes
 
 @DFExperimental
 class FrontMatterEnvelopeFormat(
@@ -22,7 +21,7 @@ class FrontMatterEnvelopeFormat(
         var offset = 0u
         do {
             line = readUtf8Line() //?: error("Input does not contain front matter separator")
-            offset += line.toUtf8Bytes().size.toUInt()
+            offset += line.toByteArray().size.toUInt()
         } while (!line.startsWith(SEPARATOR))
 
         val readMetaFormat =
@@ -34,7 +33,7 @@ class FrontMatterEnvelopeFormat(
             do {
                 line = readUtf8Line()
                 writeUtf8String(line + "\r\n")
-                offset += line.toUtf8Bytes().size.toUInt()
+                offset += line.toByteArray().size.toUInt()
             } while (!line.startsWith(SEPARATOR))
         }.read {
             readMetaFormat.run {
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt
index d7c60116..ba03e2ed 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt
@@ -28,7 +28,7 @@ interface Envelope {
         /**
          * Build a static envelope using provided builder
          */
-        inline operator fun invoke(block: EnvelopeBuilder.() -> Unit) = EnvelopeBuilder().apply(block).build()
+        inline operator fun invoke(block: EnvelopeBuilder.() -> Unit) = EnvelopeBuilder().apply(block).seal()
     }
 }
 
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeBuilder.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeBuilder.kt
index c37f7c38..73775af3 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeBuilder.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeBuilder.kt
@@ -3,42 +3,44 @@ package hep.dataforge.io
 import hep.dataforge.meta.*
 import kotlinx.io.*
 
-class EnvelopeBuilder {
+public class EnvelopeBuilder : Envelope {
     private val metaBuilder = MetaBuilder()
-    var data: Binary? = null
 
-    fun meta(block: MetaBuilder.() -> Unit) {
+    override var data: Binary? = null
+    override var meta: Meta
+        get() = metaBuilder
+        set(value) {
+            metaBuilder.update(value)
+        }
+
+    public fun meta(block: MetaBuilder.() -> Unit) {
         metaBuilder.apply(block)
     }
 
-    fun meta(meta: Meta) {
-        metaBuilder.update(meta)
-    }
-
     /**
      * The general purpose of the envelope
      */
-    var type by metaBuilder.string(key = Envelope.ENVELOPE_TYPE_KEY)
-    var dataType by metaBuilder.string(key = Envelope.ENVELOPE_DATA_TYPE_KEY)
+    public var type: String? by metaBuilder.string(key = Envelope.ENVELOPE_TYPE_KEY)
+    public var dataType: String? by metaBuilder.string(key = Envelope.ENVELOPE_DATA_TYPE_KEY)
 
     /**
      * Data unique identifier to bypass identity checks
      */
-    var dataID by metaBuilder.string(key = Envelope.ENVELOPE_DATA_ID_KEY)
-    var description by metaBuilder.string(key = Envelope.ENVELOPE_DESCRIPTION_KEY)
-    var name by metaBuilder.string(key = Envelope.ENVELOPE_NAME_KEY)
+    public var dataID: String? by metaBuilder.string(key = Envelope.ENVELOPE_DATA_ID_KEY)
+    public var description: String? by metaBuilder.string(key = Envelope.ENVELOPE_DESCRIPTION_KEY)
+    public var name: String? by metaBuilder.string(key = Envelope.ENVELOPE_NAME_KEY)
 
     /**
      * Construct a data binary from given builder
      */
     @OptIn(ExperimentalIoApi::class)
-    fun data(block: Output.() -> Unit) {
+    public fun data(block: Output.() -> Unit) {
         val arrayBuilder = ByteArrayOutput()
         arrayBuilder.block()
         data = arrayBuilder.toByteArray().asBinary()
     }
 
-    fun build() = SimpleEnvelope(metaBuilder.seal(), data)
+    public fun seal(): Envelope = SimpleEnvelope(metaBuilder.seal(), data)
 
 }
 
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
index e19a9f7d..96fab099 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
@@ -14,25 +14,24 @@ import kotlinx.io.Input
 import kotlinx.io.Output
 import kotlinx.io.readByteArray
 import kotlinx.io.text.writeUtf8String
-import kotlinx.serialization.UnstableDefault
 import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.JsonObjectSerializer
+import kotlinx.serialization.json.JsonObject
+
 
-@OptIn(UnstableDefault::class)
 class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat {
 
     override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) {
         val jsonObject = meta.toJson(descriptor)
-        writeUtf8String(json.stringify(JsonObjectSerializer, jsonObject))
+        writeUtf8String(json.encodeToString(JsonObject.serializer(), jsonObject))
     }
 
-    override fun toMeta(): Meta  = Meta{
+    override fun toMeta(): Meta = Meta {
         NAME_KEY put name.toString()
     }
 
     override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
         val str = readByteArray().decodeToString()
-        val jsonElement = json.parseJson(str)
+        val jsonElement = json.parseToJsonElement(str)
         val item = jsonElement.toMetaItem(descriptor)
         return item.node ?: Meta.EMPTY
     }
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt
index 9b214c5c..edb05bf5 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt
@@ -9,7 +9,7 @@ fun Output.writeRawString(str: String) {
 
 fun Input.readRawString(size: Int): String {
     val array = CharArray(size) { readByte().toChar() }
-    return String(array)
+    return array.concatToString()
 }
 
 inline fun buildByteArray(expectedSize: Int = 16, block: Output.() -> Unit): ByteArray =
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt
index a470cf0a..247f937e 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt
@@ -3,9 +3,7 @@ package hep.dataforge.io
 import hep.dataforge.meta.*
 import hep.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY
 import kotlinx.io.asBinary
-import kotlinx.serialization.json.JsonPrimitive
-import kotlinx.serialization.json.json
-import kotlinx.serialization.json.jsonArray
+import kotlinx.serialization.json.*
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
@@ -57,21 +55,21 @@ class MetaFormatTest {
 
     @Test
     fun testJsonToMeta() {
-        val json = jsonArray {
+        val json = buildJsonArray {
             //top level array
-            +jsonArray {
-                +JsonPrimitive(88)
-                +json {
-                    "c" to "aasdad"
-                    "d" to true
-                }
-            }
-            +"value"
-            +jsonArray {
-                +JsonPrimitive(1.0)
-                +JsonPrimitive(2.0)
-                +JsonPrimitive(3.0)
-            }
+            add(buildJsonArray {
+                add(JsonPrimitive(88))
+                add(buildJsonObject {
+                    put("c", "aasdad")
+                    put("d", true)
+                })
+            })
+            add("value")
+            add(buildJsonArray {
+                add(JsonPrimitive(1.0))
+                add(JsonPrimitive(2.0))
+                add(JsonPrimitive(3.0))
+            })
         }
         val meta = json.toMetaItem().node!!
 
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
index ef301710..1f3b235d 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
@@ -19,24 +19,24 @@ class MetaSerializerTest {
 
     @Test
     fun testMetaSerialization() {
-        val string = JSON_PRETTY.stringify(MetaSerializer, meta)
-        val restored = JSON_PLAIN.parse(MetaSerializer, string)
+        val string = JSON_PRETTY.encodeToString(MetaSerializer, meta)
+        val restored = JSON_PLAIN.decodeFromString(MetaSerializer, string)
         assertEquals(meta, restored)
     }
 
     @Test
     fun testCborSerialization() {
-        val bytes = Cbor.dump(MetaSerializer, meta)
+        val bytes = Cbor.encodeToByteArray(MetaSerializer, meta)
         println(bytes.contentToString())
-        val restored = Cbor.load(MetaSerializer, bytes)
+        val restored = Cbor.decodeFromByteArray(MetaSerializer, bytes)
         assertEquals(meta, restored)
     }
 
     @Test
     fun testNameSerialization() {
         val name = "a.b.c".toName()
-        val string = JSON_PRETTY.stringify(Name.serializer(), name)
-        val restored = JSON_PLAIN.parse(Name.serializer(), string)
+        val string = JSON_PRETTY.encodeToString(Name.serializer(), name)
+        val restored = JSON_PLAIN.decodeFromString(Name.serializer(), string)
         assertEquals(name, restored)
     }
 
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
index 156acd89..4e7a4243 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
@@ -11,10 +11,11 @@ import java.util.concurrent.Executors
 import kotlin.time.ExperimentalTime
 
 @ExperimentalTime
-class EnvelopeClient(
+@Deprecated("To be replaced by flow-based client")
+public class EnvelopeClient(
     override val context: Context,
-    val host: String,
-    val port: Int,
+    public val host: String,
+    public val port: Int,
     formatFactory: EnvelopeFormatFactory = TaggedEnvelopeFormat,
     formatMeta: Meta = Meta.EMPTY
 ) : Responder, ContextAware {
@@ -34,7 +35,7 @@ class EnvelopeClient(
 //        }
 //    }
 
-    suspend fun close() {
+    public suspend fun close() {
         try {
             respond(
                 Envelope {
@@ -47,6 +48,7 @@ class EnvelopeClient(
     }
 
 
+    @Suppress("BlockingMethodInNonBlockingContext")
     override suspend fun respond(request: Envelope): Envelope = withContext(dispatcher) {
         //val address = InetSocketAddress(host,port)
         val socket = Socket(host, port)
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
index b9569279..3f83e841 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
@@ -12,7 +12,8 @@ import java.net.ServerSocket
 import java.net.Socket
 import kotlin.concurrent.thread
 
-class EnvelopeServer(
+@Deprecated("To be replaced by flow-based server")
+public class EnvelopeServer(
     override val context: Context,
     val port: Int,
     val responder: Responder,
@@ -25,7 +26,7 @@ class EnvelopeServer(
 
     private val format = formatFactory(formatMeta, context = context)
 
-    fun start() {
+    public fun start() {
         if (job == null) {
             logger.info { "Starting envelope server on port $port" }
             job = scope.launch(Dispatchers.IO) {
@@ -40,7 +41,7 @@ class EnvelopeServer(
         }
     }
 
-    fun stop() {
+    public fun stop() {
         logger.info { "Stopping envelope server on port $port" }
         job?.cancel()
         job = null
@@ -97,7 +98,7 @@ class EnvelopeServer(
         }
     }
 
-    companion object {
-        const val SHUTDOWN_ENVELOPE_TYPE = "@shutdown"
+    public companion object {
+        public const val SHUTDOWN_ENVELOPE_TYPE = "@shutdown"
     }
 }
\ No newline at end of file
diff --git a/dataforge-meta/build.gradle.kts b/dataforge-meta/build.gradle.kts
index f19a39fc..78a9a895 100644
--- a/dataforge-meta/build.gradle.kts
+++ b/dataforge-meta/build.gradle.kts
@@ -1,9 +1,9 @@
-import scientifik.useSerialization
-
 plugins {
-    id("scientifik.mpp")
+    id("kscience.mpp")
 }
 
-useSerialization()
+kscience {
+    useSerialization()
+}
 
 description = "Meta definition and basic operations on meta"
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
index 0ac29d86..376663d0 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
@@ -4,16 +4,26 @@ import hep.dataforge.names.Name
 import hep.dataforge.names.NameToken
 import hep.dataforge.names.asName
 import hep.dataforge.names.plus
-import kotlinx.serialization.*
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.Serializer
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+import kotlin.collections.HashSet
+import kotlin.collections.forEach
+import kotlin.collections.mapValues
+import kotlin.collections.removeAll
+import kotlin.collections.set
 
 //TODO add validator to configuration
 
-data class MetaListener(
+public data class MetaListener(
     val owner: Any? = null,
     val action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit
 )
 
-interface ObservableMeta : Meta {
+public interface ObservableMeta : Meta {
     fun onChange(owner: Any?, action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit)
     fun removeListener(owner: Any?)
 }
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
index debe3080..582890cf 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
@@ -61,9 +61,9 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
                 elementMap[jsonKey] = items.values.first().toJsonElement(itemDescriptor, null)
             }
             else -> {
-                val array = jsonArray {
+                val array = buildJsonArray {
                     items.forEach { (index, item) ->
-                        +item.toJsonElement(itemDescriptor, index)
+                        add(item.toJsonElement(itemDescriptor, index))
                     }
                 }
                 elementMap[jsonKey] = array
@@ -89,16 +89,11 @@ fun JsonObject.toMeta(descriptor: NodeDescriptor? = null): JsonMeta = JsonMeta(t
 fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
     return when (this) {
         JsonNull -> Null
-        is JsonLiteral -> {
-            when (body) {
-                true -> True
-                false -> False
-                is Number -> NumberValue(body as Number)
-                else -> if (isString) {
-                    StringValue(content)
-                } else {
-                    content.parseValue()
-                }
+        else -> {
+            if (isString) {
+                StringValue(content)
+            } else {
+                content.parseValue()
             }
         }
     }
@@ -126,7 +121,7 @@ fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMet
             MetaItem.ValueItem(value)
         } else {
             //We can't return multiple items therefore we create top level node
-            json { JSON_ARRAY_KEY to this@toMetaItem }.toMetaItem(descriptor)
+            buildJsonObject { put(JSON_ARRAY_KEY, this@toMetaItem) }.toMetaItem(descriptor)
         }
     }
 }
@@ -165,7 +160,7 @@ class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : M
                 } else value.forEachIndexed { index, jsonElement ->
                     val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: NodeDescriptor.DEFAULT_INDEX_KEY
                     val indexValue: String = (jsonElement as? JsonObject)
-                        ?.get(indexKey)?.contentOrNull
+                        ?.get(indexKey)?.jsonPrimitive?.contentOrNull
                         ?: index.toString() //In case index is non-string, the backward transformation will be broken.
 
                     val token = key.withIndex(indexValue)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
index d01e9786..25d89860 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
@@ -5,7 +5,12 @@ import hep.dataforge.meta.MetaItem.NodeItem
 import hep.dataforge.meta.MetaItem.ValueItem
 import hep.dataforge.names.*
 import hep.dataforge.values.*
-import kotlinx.serialization.*
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.Serializer
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
 
 
 /**
@@ -218,7 +223,7 @@ abstract class MetaBase : Meta {
 
     override fun hashCode(): Int = items.hashCode()
 
-    override fun toString(): String = JSON_PRETTY.stringify(MetaSerializer, this)
+    override fun toString(): String = JSON_PRETTY.encodeToString(MetaSerializer, this)
 }
 
 /**
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
index 6f0db59e..d8f82a9b 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
@@ -1,11 +1,15 @@
 package hep.dataforge.meta
 
 import hep.dataforge.names.NameToken
-import kotlinx.serialization.*
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializer
 import kotlinx.serialization.builtins.MapSerializer
-import kotlinx.serialization.json.JsonInput
-import kotlinx.serialization.json.JsonObjectSerializer
-import kotlinx.serialization.json.JsonOutput
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+import kotlinx.serialization.json.JsonDecoder
+import kotlinx.serialization.json.JsonEncoder
+import kotlinx.serialization.json.JsonObject
 
 
 /**
@@ -21,8 +25,8 @@ object MetaSerializer : KSerializer<Meta> {
     override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
 
     override fun deserialize(decoder: Decoder): Meta {
-        return if (decoder is JsonInput) {
-            JsonObjectSerializer.deserialize(decoder).toMeta()
+        return if (decoder is JsonDecoder) {
+            JsonObject.serializer().deserialize(decoder).toMeta()
         } else {
             object : MetaBase() {
                 override val items: Map<NameToken, MetaItem<*>> = mapSerializer.deserialize(decoder)
@@ -31,8 +35,8 @@ object MetaSerializer : KSerializer<Meta> {
     }
 
     override fun serialize(encoder: Encoder, value: Meta) {
-        if (encoder is JsonOutput) {
-            JsonObjectSerializer.serialize(encoder, value.toJson())
+        if (encoder is JsonEncoder) {
+            JsonObject.serializer().serialize(encoder, value.toJson())
         } else {
             mapSerializer.serialize(encoder, value.items)
         }
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
index 13965505..e782db30 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
@@ -163,7 +163,7 @@ fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
     if (newIndex != null) {
         set(name, value)
     } else {
-        val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.max() ?: -1) + 1
+        val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.maxOrNull() ?: -1) + 1
         set(name.withIndex(index.toString()), value)
     }
 }
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt
index f06bb06a..c3f78fe9 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt
@@ -1,42 +1,50 @@
 package hep.dataforge.meta
 
-import kotlinx.serialization.*
+import kotlinx.serialization.InternalSerializationApi
 import kotlinx.serialization.builtins.DoubleArraySerializer
 import kotlinx.serialization.builtins.serializer
+import kotlinx.serialization.descriptors.*
+import kotlinx.serialization.encoding.CompositeDecoder
+import kotlinx.serialization.encoding.CompositeEncoder
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
 import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.JsonConfiguration
 
-fun SerialDescriptorBuilder.boolean(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
+fun ClassSerialDescriptorBuilder.boolean(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
     element(name, Boolean.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
 
-fun SerialDescriptorBuilder.string(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
+fun ClassSerialDescriptorBuilder.string(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
     element(name, String.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
 
-fun SerialDescriptorBuilder.int(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
+fun ClassSerialDescriptorBuilder.int(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
     element(name, Int.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
 
-fun SerialDescriptorBuilder.double(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
+fun ClassSerialDescriptorBuilder.double(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
     element(name, Double.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
 
-fun SerialDescriptorBuilder.float(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
+fun ClassSerialDescriptorBuilder.float(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
     element(name, Float.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
 
-fun SerialDescriptorBuilder.long(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
+fun ClassSerialDescriptorBuilder.long(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
     element(name, Long.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
 
-fun SerialDescriptorBuilder.doubleArray(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
+fun ClassSerialDescriptorBuilder.doubleArray(
+    name: String,
+    isOptional: Boolean = false,
+    vararg annotations: Annotation,
+) =
     element(name, DoubleArraySerializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
 
 @OptIn(InternalSerializationApi::class)
-inline fun <reified E : Enum<E>> SerialDescriptorBuilder.enum(
+inline fun <reified E : Enum<E>> ClassSerialDescriptorBuilder.enum(
     name: String,
     isOptional: Boolean = false,
-    vararg annotations: Annotation
+    vararg annotations: Annotation,
 ) {
-    val enumDescriptor = SerialDescriptor(serialName, UnionKind.ENUM_KIND) {
+    val enumDescriptor = buildSerialDescriptor(serialName, SerialKind.ENUM) {
         enumValues<E>().forEach {
             val fqn = "$serialName.${it.name}"
-            val enumMemberDescriptor = SerialDescriptor(fqn, StructureKind.OBJECT)
+            val enumMemberDescriptor = buildSerialDescriptor(fqn, StructureKind.OBJECT)
             element(it.name, enumMemberDescriptor)
         }
     }
@@ -46,10 +54,9 @@ inline fun <reified E : Enum<E>> SerialDescriptorBuilder.enum(
 @DFExperimental
 inline fun <R> Decoder.decodeStructure(
     desc: SerialDescriptor,
-    vararg typeParams: KSerializer<*> = emptyArray(),
-    crossinline block: CompositeDecoder.() -> R
+    crossinline block: CompositeDecoder.() -> R,
 ): R {
-    val decoder = beginStructure(desc, *typeParams)
+    val decoder = beginStructure(desc)
     val res = decoder.block()
     decoder.endStructure(desc)
     return res
@@ -58,15 +65,12 @@ inline fun <R> Decoder.decodeStructure(
 @DFExperimental
 inline fun Encoder.encodeStructure(
     desc: SerialDescriptor,
-    vararg typeParams: KSerializer<*> = emptyArray(),
-    block: CompositeEncoder.() -> Unit
+    block: CompositeEncoder.() -> Unit,
 ) {
-    val encoder = beginStructure(desc, *typeParams)
+    val encoder = beginStructure(desc)
     encoder.block()
     encoder.endStructure(desc)
 }
 
-@OptIn(UnstableDefault::class)
-val JSON_PRETTY = Json(JsonConfiguration(prettyPrint = true, useArrayPolymorphism = true))
-@OptIn(UnstableDefault::class)
-val JSON_PLAIN = Json(JsonConfiguration(prettyPrint = true, useArrayPolymorphism = true))
\ No newline at end of file
+val JSON_PRETTY = Json { prettyPrint = true; useArrayPolymorphism = true }
+val JSON_PLAIN = Json { prettyPrint = false; useArrayPolymorphism = true }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
index 5ed2ff81..327291d0 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
@@ -1,6 +1,13 @@
 package hep.dataforge.names
 
-import kotlinx.serialization.*
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.Serializer
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
 
 
 /**
@@ -60,7 +67,7 @@ class Name(val tokens: List<NameToken>) {
         val EMPTY = Name(emptyList())
 
         override val descriptor: SerialDescriptor =
-            PrimitiveDescriptor("hep.dataforge.names.Name", PrimitiveKind.STRING)
+            PrimitiveSerialDescriptor("hep.dataforge.names.Name", PrimitiveKind.STRING)
 
         override fun deserialize(decoder: Decoder): Name {
             return decoder.decodeString().toName()
@@ -101,7 +108,7 @@ data class NameToken(val body: String, val index: String? = null) {
     @Serializer(NameToken::class)
     companion object : KSerializer<NameToken> {
         override val descriptor: SerialDescriptor =
-            PrimitiveDescriptor("hep.dataforge.names.NameToken", PrimitiveKind.STRING)
+            PrimitiveSerialDescriptor("hep.dataforge.names.NameToken", PrimitiveKind.STRING)
 
         override fun deserialize(decoder: Decoder): NameToken {
             return decoder.decodeString().toName().first()!!
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
index 8055b554..ad57cb71 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
@@ -3,22 +3,27 @@ package hep.dataforge.values
 import hep.dataforge.meta.boolean
 import hep.dataforge.meta.enum
 import hep.dataforge.meta.string
-import kotlinx.serialization.*
-import kotlinx.serialization.builtins.list
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializer
+import kotlinx.serialization.builtins.ListSerializer
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.descriptors.buildClassSerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
 
 @Serializer(Value::class)
 object ValueSerializer : KSerializer<Value> {
-    private val listSerializer by lazy { ValueSerializer.list }
+    private val listSerializer by lazy { ListSerializer(ValueSerializer) }
 
     override val descriptor: SerialDescriptor =
-        SerialDescriptor("hep.dataforge.values.Value") {
+        buildClassSerialDescriptor("hep.dataforge.values.Value") {
             boolean("isList")
             enum<ValueType>("valueType")
             string("value")
         }
 
     private fun Decoder.decodeValue(): Value {
-        return when (decode(ValueType.serializer())) {
+        return when (decodeSerializableValue(ValueType.serializer())) {
             ValueType.NULL -> Null
             ValueType.NUMBER -> decodeDouble().asValue() //TODO differentiate?
             ValueType.BOOLEAN -> decodeBoolean().asValue()
@@ -37,7 +42,7 @@ object ValueSerializer : KSerializer<Value> {
     }
 
     private fun Encoder.encodeValue(value: Value) {
-        encode(ValueType.serializer(), value.type)
+        encodeSerializableValue(ValueType.serializer(), value.type)
         when (value.type) {
             ValueType.NULL -> {
                 // do nothing
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/JsonMetaTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/JsonMetaTest.kt
index 9086e156..2a1329a7 100644
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/JsonMetaTest.kt
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/JsonMetaTest.kt
@@ -1,35 +1,33 @@
 package hep.dataforge.meta
 
 import hep.dataforge.meta.descriptors.NodeDescriptor
-import kotlinx.serialization.json.int
-import kotlinx.serialization.json.json
-import kotlinx.serialization.json.jsonArray
+import kotlinx.serialization.json.*
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
 class JsonMetaTest {
-    val json = json {
-        "firstValue" to "a"
-        "secondValue" to "b"
-        "array" to jsonArray {
-            +"1"
-            +"2"
-            +"3"
-        }
-        "nodeArray" to jsonArray {
-            +json {
-                "index" to "1"
-                "value" to 2
-            }
-            +json {
-                "index" to "2"
-                "value" to 3
-            }
-            +json {
-                "index" to "3"
-                "value" to 4
-            }
-        }
+    val json = buildJsonObject {
+        put("firstValue", "a")
+        put("secondValue", "b")
+        put("array", buildJsonArray {
+            add("1")
+            add("2")
+            add("3")
+        })
+        put("nodeArray", buildJsonArray {
+            add(buildJsonObject {
+                put("index", "1")
+                put("value", 2)
+            })
+            add(buildJsonObject {
+                put("index", "2")
+                put("value", 3)
+            })
+            add(buildJsonObject {
+                put("index", "3")
+                put("value", 4)
+            })
+        })
     }
 
     val descriptor = NodeDescriptor{
@@ -45,7 +43,8 @@ class JsonMetaTest {
         //println(meta)
         val reconstructed = meta.toJson(descriptor)
         println(reconstructed)
-        assertEquals(2, reconstructed["nodeArray"]?.jsonArray?.get(1)?.jsonObject?.get("index")?.int)
+        assertEquals(2,
+            reconstructed["nodeArray"]?.jsonArray?.get(1)?.jsonObject?.get("index")?.jsonPrimitive?.int)
         assertEquals(json,reconstructed)
     }
 }
\ No newline at end of file
diff --git a/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt b/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt
index ff23a571..d131fb59 100644
--- a/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt
+++ b/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt
@@ -38,7 +38,7 @@ fun Meta.toDynamic(): dynamic {
     return res
 }
 
-class DynamicMeta(val obj: dynamic) : MetaBase() {
+public class DynamicMeta(public val obj: dynamic) : MetaBase() {
     private fun keys() = js("Object.keys(this.obj)") as Array<String>
 
     private fun isArray(@Suppress("UNUSED_PARAMETER") obj: dynamic): Boolean =
@@ -47,7 +47,7 @@ class DynamicMeta(val obj: dynamic) : MetaBase() {
     private fun isPrimitive(obj: dynamic): Boolean =
         (jsTypeOf(obj) != "object")
 
-    @Suppress("UNCHECKED_CAST")
+    @Suppress("UNCHECKED_CAST", "USELESS_CAST")
     private fun asItem(obj: dynamic): MetaItem<DynamicMeta>? {
         return when {
             obj == null -> MetaItem.ValueItem(Null)
diff --git a/dataforge-output/build.gradle.kts b/dataforge-output/build.gradle.kts
index 6c0a1e53..d84333ba 100644
--- a/dataforge-output/build.gradle.kts
+++ b/dataforge-output/build.gradle.kts
@@ -1,5 +1,5 @@
 plugins {
-    id("scientifik.mpp")
+    id("kscience.mpp")
 }
 
 kotlin {
diff --git a/dataforge-output/dataforge-output-html/build.gradle.kts b/dataforge-output/dataforge-output-html/build.gradle.kts
index 98b9d0bd..fe2de0b9 100644
--- a/dataforge-output/dataforge-output-html/build.gradle.kts
+++ b/dataforge-output/dataforge-output-html/build.gradle.kts
@@ -1,25 +1,15 @@
 plugins {
-    id("scientifik.mpp")
+    id("kscience.mpp")
 }
 
-val htmlVersion by rootProject.extra("0.6.12")
+val htmlVersion by rootProject.extra("0.7.2")
 
 kotlin {
     sourceSets {
         val commonMain by getting {
             dependencies {
                 api(project(":dataforge-output"))
-                api("org.jetbrains.kotlinx:kotlinx-html-common:$htmlVersion")
-            }
-        }
-        val jsMain by getting {
-            dependencies {
-                api("org.jetbrains.kotlinx:kotlinx-html-js:$htmlVersion")
-            }
-        }
-        val jvmMain by getting{
-            dependencies {
-                api("org.jetbrains.kotlinx:kotlinx-html-jvm:$htmlVersion")
+                api("org.jetbrains.kotlinx:kotlinx-html:$htmlVersion")
             }
         }
     }
diff --git a/dataforge-scripting/build.gradle.kts b/dataforge-scripting/build.gradle.kts
index c848c1b1..16ab6559 100644
--- a/dataforge-scripting/build.gradle.kts
+++ b/dataforge-scripting/build.gradle.kts
@@ -1,9 +1,8 @@
 plugins {
-    id("scientifik.mpp")
+    id("kscience.mpp")
 }
 
 kotlin {
-    jvm()
     sourceSets {
         val commonMain by getting {
             dependencies {
@@ -13,7 +12,7 @@ kotlin {
         }
         val jvmMain by getting {
             dependencies {
-                implementation(kotlin("scripting-jvm-host-embeddable"))
+                implementation(kotlin("scripting-jvm-host"))
                 implementation(kotlin("scripting-jvm"))
             }
         }
diff --git a/dataforge-tables/build.gradle.kts b/dataforge-tables/build.gradle.kts
index 6c0a1e53..d84333ba 100644
--- a/dataforge-tables/build.gradle.kts
+++ b/dataforge-tables/build.gradle.kts
@@ -1,5 +1,5 @@
 plugins {
-    id("scientifik.mpp")
+    id("kscience.mpp")
 }
 
 kotlin {
diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts
index c576ef8e..5d745ff8 100644
--- a/dataforge-workspace/build.gradle.kts
+++ b/dataforge-workspace/build.gradle.kts
@@ -1,10 +1,8 @@
 plugins {
-    id("scientifik.mpp")
+    id("kscience.mpp")
 }
 
 kotlin {
-    jvm()
-    js()
     sourceSets {
         val commonMain by getting{
             dependencies {
diff --git a/gradle/artifactory.gradle b/gradle/artifactory.gradle
deleted file mode 100644
index 12e59642..00000000
--- a/gradle/artifactory.gradle
+++ /dev/null
@@ -1,31 +0,0 @@
-apply plugin: "com.jfrog.artifactory"
-
-artifactory {
-    def artifactory_user = project.hasProperty('artifactoryUser') ? project.property('artifactoryUser') : ""
-    def artifactory_password = project.hasProperty('artifactoryPassword') ? project.property('artifactoryPassword') : ""
-    def artifactory_contextUrl = 'http://npm.mipt.ru:8081/artifactory'
-    
-    contextUrl = artifactory_contextUrl   //The base Artifactory URL if not overridden by the publisher/resolver
-    publish {
-        repository {
-            repoKey = 'gradle-dev-local'
-            username = artifactory_user
-            password = artifactory_password
-        }
-
-        defaults {
-            publications('jvm', 'js', 'kotlinMultiplatform', 'metadata')
-            publishBuildInfo = false
-            publishArtifacts = true
-            publishPom = true
-            publishIvy = false
-        }
-    }
-    resolve {
-        repository {
-            repoKey = 'gradle-dev'
-            username = artifactory_user
-            password = artifactory_password
-        }
-    }
-}
\ No newline at end of file
diff --git a/gradle/bintray.gradle b/gradle/bintray.gradle
deleted file mode 100644
index 8da83c86..00000000
--- a/gradle/bintray.gradle
+++ /dev/null
@@ -1,85 +0,0 @@
-apply plugin: 'com.jfrog.bintray'
-
-def vcs = "https://github.com/mipt-npm/kmath"
-
-def pomConfig = {
-    licenses {
-        license {
-            name "The Apache Software License, Version 2.0"
-            url "http://www.apache.org/licenses/LICENSE-2.0.txt"
-            distribution "repo"
-        }
-    }
-    developers {
-        developer {
-            id "MIPT-NPM"
-            name "MIPT nuclear physics methods laboratory"
-            organization "MIPT"
-            organizationUrl "http://npm.mipt.ru"
-        }
-    }
-    scm {
-        url vcs
-    }
-}
-
-project.ext.configureMavenCentralMetadata = { pom ->
-    def root = asNode()
-    root.appendNode('name', project.name)
-    root.appendNode('description', project.description)
-    root.appendNode('url', vcs)
-    root.children().last() + pomConfig
-}
-
-project.ext.configurePom = pomConfig
-
-
-// Configure publishing
-publishing {
-    repositories {
-        maven {
-            url = "https://bintray.com/mipt-npm/scientifik"
-        }
-    }
-
-    // Process each publication we have in this project
-    publications.all { publication ->
-        // apply changes to pom.xml files, see pom.gradle
-        pom.withXml(configureMavenCentralMetadata)
-
-
-    }
-}
-
-bintray {
-    user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER')
-    key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY')
-    publish = true
-    override = true // for multi-platform Kotlin/Native publishing
-
-    pkg {
-        userOrg = "mipt-npm"
-        repo = "scientifik"
-        name = "scientifik.kmath"
-        issueTrackerUrl = "https://github.com/mipt-npm/kmath/issues"
-        licenses = ['Apache-2.0']
-        vcsUrl = vcs
-        version {
-            name = project.version
-            vcsTag = project.version
-            released = new Date()
-        }
-    }
-}
-
-bintrayUpload.dependsOn publishToMavenLocal
-
-// This is for easier debugging of bintray uploading problems
-bintrayUpload.doFirst {
-    publications = project.publishing.publications.findAll {
-        !it.name.contains('-test') && it.name != 'kotlinMultiplatform'
-    }.collect {
-        println("Uploading artifact '$it.groupId:$it.artifactId:$it.version' from publication '$it.name'")
-        it.name//https://github.com/bintray/gradle-bintray-plugin/issues/256
-    }
-}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index e0d250bf..2433e4dd 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -6,21 +6,21 @@ pluginManagement {
         maven("https://dl.bintray.com/kotlin/kotlin-eap")
         maven("https://dl.bintray.com/kotlin/kotlinx")
         maven("https://dl.bintray.com/mipt-npm/scientifik")
+        maven("https://dl.bintray.com/mipt-npm/kscience")
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
+
+    val toolsVersion = "0.6.0"
+
     resolutionStrategy {
         eachPlugin {
             when (requested.id.id) {
-                "kotlinx-atomicfu" -> useModule("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${requested.version}")
-                "scientifik.mpp", "scientifik.jvm", "scientifik.publish" -> useModule("scientifik:gradle-tools:${requested.version}")
+                "kscience.mpp", "kscience.jvm", "kscience.js", "kscience.publish" -> useModule("ru.mipt.npm:gradle-tools:${toolsVersion}")
             }
         }
     }
 }
 
-enableFeaturePreview("GRADLE_METADATA")
-
-//rootProject.name = "dataforge-core"
 include(
     ":dataforge-meta",
     ":dataforge-io",
@@ -32,6 +32,4 @@ include(
     ":dataforge-tables",
     ":dataforge-workspace",
     ":dataforge-scripting"
-)
-
-//includeBuild("../kotlinx-io")
\ No newline at end of file
+)
\ No newline at end of file

From 57b263ec63f018e871e134a8e3f0f9c37c61a96f Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Mon, 31 Aug 2020 11:27:44 +0300
Subject: [PATCH 10/40] Migration to 1.4

---
 build.gradle.kts                              |   7 +-
 dataforge-context/build.gradle.kts            |   8 +-
 .../kotlin/hep/dataforge/data/dataCast.kt     |   4 +-
 .../kotlin/hep/dataforge/data/dataJS.kt       |   4 +-
 .../kotlin/hep/dataforge/data/dataJVM.kt      |  10 +-
 .../kotlin/hep/dataforge/io/Consumer.kt       |  11 ++
 .../kotlin/hep/dataforge/io/Responder.kt      |  13 +--
 .../kotlin/hep/dataforge/meta/Config.kt       |  20 ++--
 .../kotlin/hep/dataforge/meta/Configurable.kt |  40 +++-----
 .../kotlin/hep/dataforge/meta/ItemDelegate.kt |  42 ++++----
 .../kotlin/hep/dataforge/meta/JsonMeta.kt     |  16 +--
 .../kotlin/hep/dataforge/meta/Laminate.kt     |  20 ++--
 .../kotlin/hep/dataforge/meta/Meta.kt         |  97 +++++++++---------
 dataforge-scripting/build.gradle.kts          |   6 +-
 .../hep/dataforge/scripting/Placeholder.kt    |   4 -
 .../hep/dataforge/scripting/Builders.kt       |  15 +--
 dataforge-workspace/build.gradle.kts          |   2 +-
 gradle/wrapper/gradle-wrapper.jar             | Bin 58910 -> 59203 bytes
 gradle/wrapper/gradle-wrapper.properties      |   2 +-
 gradlew                                       |   2 +-
 gradlew.bat                                   |  21 +---
 settings.gradle.kts                           |  10 +-
 22 files changed, 171 insertions(+), 183 deletions(-)
 create mode 100644 dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Consumer.kt
 delete mode 100644 dataforge-scripting/src/commonMain/kotlin/hep/dataforge/scripting/Placeholder.kt

diff --git a/build.gradle.kts b/build.gradle.kts
index 129a3adc..09240c13 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,13 +1,10 @@
 plugins {
-    val toolsVersion = "0.6.0"
-    id("kscience.mpp") version toolsVersion apply false
-    id("kscience.jvm") version toolsVersion apply false
-    id("kscience.publish") version toolsVersion apply false
+    id("kscience.publish") apply false
     id("org.jetbrains.dokka") version "1.4.0-rc"
     id("org.jetbrains.changelog") version "0.4.0"
 }
 
-val dataforgeVersion by extra("0.1.9-dev-1")
+val dataforgeVersion by extra("0.1.9-dev-2")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/dataforge-context/build.gradle.kts b/dataforge-context/build.gradle.kts
index 90a7a7a3..a41e4443 100644
--- a/dataforge-context/build.gradle.kts
+++ b/dataforge-context/build.gradle.kts
@@ -4,16 +4,20 @@ plugins {
 
 description = "Context and provider definitions"
 
-kscience{
+kscience {
     useCoroutines()
 }
 
+repositories {
+    maven("https://maven.pkg.github.com/altavir/kotlin-logging")
+}
+
 kotlin {
     sourceSets {
         val commonMain by getting {
             dependencies {
                 api(project(":dataforge-meta"))
-                api("io.github.microutils:kotlin-logging:1.9.0")
+                api("io.github.microutils:kotlin-logging:1.9.0-dev-npm")
             }
         }
         val jvmMain by getting {
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt
index 21301dd4..db8b7ab5 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt
@@ -20,12 +20,12 @@ inline fun <reified R : Any, T : R> Data<T>.upcast(): Data<R> = upcast(R::class)
 /**
  * Check if node could be safely cast to given class
  */
-expect fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean
+internal expect fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean
 
 /**
  * Check if data could be safely cast to given class
  */
-expect fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean
+internal expect fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean
 
 fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
     is DataItem.Node -> node.canCast(type)
diff --git a/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt b/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt
index 54148bc5..afdb032e 100644
--- a/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt
+++ b/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt
@@ -5,12 +5,12 @@ import kotlin.reflect.KClass
 /**
  * Check that node is compatible with given type meaning that each element could be cast to the type
  */
-actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
+internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
     //Not supported in js yet
     return true
 }
 
-actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
+internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
     //Not supported in js yet
     return true
 }
diff --git a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
index f354c2f7..e385acc3 100644
--- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
+++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
@@ -8,28 +8,28 @@ import kotlin.reflect.full.isSuperclassOf
 /**
  * Block the thread and get data content
  */
-fun <T : Any> Data<T>.get(): T = runBlocking { await() }
+public fun <T : Any> Data<T>.get(): T = runBlocking { await() }
 
 /**
  * Check that node is compatible with given type meaning that each element could be cast to the type
  */
-actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
+internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
     type.isSuperclassOf(type)
 
-actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
+internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
     this.type.isSubclassOf(type)
 
 /**
  * Cast the node to given type if the cast is possible or return null
  */
-fun <R : Any> Data<*>.filterIsInstance(type: KClass<out R>): Data<R>? =
+public fun <R : Any> Data<*>.filterIsInstance(type: KClass<out R>): Data<R>? =
     if (canCast(type)) cast(type) else null
 
 /**
  * Filter a node by data and node type. Resulting node and its subnodes is guaranteed to have border type [type],
  * but could contain empty nodes
  */
-fun <R : Any> DataNode<*>.filterIsInstance(type: KClass<out R>): DataNode<R> {
+public fun <R : Any> DataNode<*>.filterIsInstance(type: KClass<out R>): DataNode<R> {
     return when {
         canCast(type) -> cast(type)
         this is TypeFilteredDataNode -> origin.filterIsInstance(type)
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Consumer.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Consumer.kt
new file mode 100644
index 00000000..0ef5d327
--- /dev/null
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Consumer.kt
@@ -0,0 +1,11 @@
+package hep.dataforge.io
+
+import hep.dataforge.meta.DFExperimental
+
+/**
+ * A fire-and-forget consumer of messages
+ */
+@DFExperimental
+public interface Consumer {
+    public fun consume(message: Envelope): Unit
+}
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt
index c0214e7b..2710ffa9 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt
@@ -1,21 +1,12 @@
 package hep.dataforge.io
 
-import hep.dataforge.meta.DFExperimental
-
 /**
  * An object that could respond to external messages asynchronously
  */
-interface Responder {
+public interface Responder {
     /**
      * Send a request and wait for response for this specific request
      */
-    suspend fun respond(request: Envelope): Envelope
+    public suspend fun respond(request: Envelope): Envelope
 }
 
-/**
- * A fire-and-forget consumer of messages
- */
-@DFExperimental
-interface Consumer {
-    fun consume(message: Envelope): Unit
-}
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
index 376663d0..89d944a7 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
@@ -4,16 +4,13 @@ import hep.dataforge.names.Name
 import hep.dataforge.names.NameToken
 import hep.dataforge.names.asName
 import hep.dataforge.names.plus
+import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.Serializer
 import kotlinx.serialization.descriptors.SerialDescriptor
 import kotlinx.serialization.encoding.Decoder
 import kotlinx.serialization.encoding.Encoder
-import kotlin.collections.HashSet
-import kotlin.collections.forEach
-import kotlin.collections.mapValues
-import kotlin.collections.removeAll
 import kotlin.collections.set
 
 //TODO add validator to configuration
@@ -24,15 +21,15 @@ public data class MetaListener(
 )
 
 public interface ObservableMeta : Meta {
-    fun onChange(owner: Any?, action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit)
-    fun removeListener(owner: Any?)
+    public fun onChange(owner: Any?, action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit)
+    public fun removeListener(owner: Any?)
 }
 
 /**
  * Mutable meta representing object state
  */
 @Serializable
-class Config : AbstractMutableMeta<Config>(), ObservableMeta {
+public class Config : AbstractMutableMeta<Config>(), ObservableMeta {
 
     private val listeners = HashSet<MetaListener>()
 
@@ -78,10 +75,11 @@ class Config : AbstractMutableMeta<Config>(), ObservableMeta {
 
     override fun empty(): Config = Config()
 
+    @OptIn(ExperimentalSerializationApi::class)
     @Serializer(Config::class)
-    companion object ConfigSerializer : KSerializer<Config> {
+    public companion object ConfigSerializer : KSerializer<Config> {
 
-        fun empty(): Config = Config()
+        public fun empty(): Config = Config()
         override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
 
         override fun deserialize(decoder: Decoder): Config {
@@ -94,9 +92,9 @@ class Config : AbstractMutableMeta<Config>(), ObservableMeta {
     }
 }
 
-operator fun Config.get(token: NameToken): MetaItem<Config>? = items[token]
+public operator fun Config.get(token: NameToken): MetaItem<Config>? = items[token]
 
-fun Meta.asConfig(): Config = this as? Config ?: Config().also { builder ->
+public fun Meta.asConfig(): Config = this as? Config ?: Config().also { builder ->
     this.items.mapValues { entry ->
         val item = entry.value
         builder[entry.key.asName()] = when (item) {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
index a984b897..9fd6cdb3 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
@@ -14,21 +14,21 @@ import kotlin.reflect.KProperty
  * It is not possible to know if some property is declared by provider just by looking on [Configurable],
  * this information should be provided externally.
  */
-interface Configurable : Described, MutableItemProvider {
+public interface Configurable : Described, MutableItemProvider {
     /**
      * Backing config
      */
-    val config: Config
+    public val config: Config
 
     /**
      * Default meta item provider
      */
-    fun getDefaultItem(name: Name): MetaItem<*>? = null
+    public fun getDefaultItem(name: Name): MetaItem<*>? = null
 
     /**
      * Check if property with given [name] could be assigned to [item]
      */
-    fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
+    public fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
         val descriptor = descriptor?.get(name)
         return descriptor?.validateItem(item) ?: true
     }
@@ -53,40 +53,32 @@ interface Configurable : Described, MutableItemProvider {
     }
 }
 
-/**
- * Reset the property to its default value
- */
-@Deprecated("To be removed since unused", ReplaceWith("setItem(name, null)"))
-fun Configurable.resetProperty(name: Name) {
-    setItem(name, null)
-}
+public fun Configurable.getItem(key: String): MetaItem<*>? = getItem(key.toName())
 
-fun Configurable.getItem(key: String) = getItem(key.toName())
+public fun Configurable.setItem(name: Name, value: Value?): Unit = setItem(name, value?.let { MetaItem.ValueItem(value) })
+public fun Configurable.setItem(name: Name, meta: Meta?): Unit = setItem(name, meta?.let { MetaItem.NodeItem(meta) })
 
-fun Configurable.setItem(name: Name, value: Value?) = setItem(name, value?.let { MetaItem.ValueItem(value) })
-fun Configurable.setItem(name: Name, meta: Meta?) = setItem(name, meta?.let { MetaItem.NodeItem(meta) })
+public fun Configurable.setItem(key: String, item: MetaItem<*>?): Unit = setItem(key.toName(), item)
 
-fun Configurable.setItem(key: String, item: MetaItem<*>?) = setItem(key.toName(), item)
+public fun Configurable.setItem(key: String, value: Value?): Unit = setItem(key, value?.let { MetaItem.ValueItem(value) })
+public fun Configurable.setItem(key: String, meta: Meta?): Unit = setItem(key, meta?.let { MetaItem.NodeItem(meta) })
 
-fun Configurable.setItem(key: String, value: Value?) = setItem(key, value?.let { MetaItem.ValueItem(value) })
-fun Configurable.setItem(key: String, meta: Meta?) = setItem(key, meta?.let { MetaItem.NodeItem(meta) })
-
-fun <T : Configurable> T.configure(meta: Meta): T = this.apply { config.update(meta) }
+public fun <T : Configurable> T.configure(meta: Meta): T = this.apply { config.update(meta) }
 
 @DFBuilder
-inline fun <T : Configurable> T.configure(action: Config.() -> Unit): T = apply { config.apply(action) }
+public inline fun <T : Configurable> T.configure(action: Config.() -> Unit): T = apply { config.apply(action) }
 
 /* Node delegates */
 
-fun Configurable.config(key: Name? = null): ReadWriteProperty<Any?, Config?> =
+public fun Configurable.config(key: Name? = null): ReadWriteProperty<Any?, Config?> =
     config.node(key)
 
-fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
+public fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
     reader = { it.node },
     writer = { it?.let { MetaItem.NodeItem(it) } }
 )
 
-fun <T : Configurable> Configurable.spec(
+public fun <T : Configurable> Configurable.spec(
     spec: Specification<T>, key: Name? = null
 ): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
     override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
@@ -100,7 +92,7 @@ fun <T : Configurable> Configurable.spec(
     }
 }
 
-fun <T : Configurable> Configurable.spec(
+public fun <T : Configurable> Configurable.spec(
     spec: Specification<T>, default: T, key: Name? = null
 ): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
     override fun getValue(thisRef: Any?, property: KProperty<*>): T {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
index cffedd82..830f4a2c 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
@@ -19,7 +19,7 @@ open class ItemDelegate(
     }
 }
 
-fun ItemProvider.item(key: Name? = null): ItemDelegate = ItemDelegate(this, key)
+public fun ItemProvider.item(key: Name? = null): ItemDelegate = ItemDelegate(this, key)
 
 //TODO add caching for sealed nodes
 
@@ -29,62 +29,62 @@ fun ItemProvider.item(key: Name? = null): ItemDelegate = ItemDelegate(this, key)
 /**
  * A property delegate that uses custom key
  */
-fun ItemProvider.value(key: Name? = null): ReadOnlyProperty<Any?, Value?> =
+public fun ItemProvider.value(key: Name? = null): ReadOnlyProperty<Any?, Value?> =
     item(key).convert(MetaConverter.value)
 
-fun ItemProvider.string(key: Name? = null): ReadOnlyProperty<Any?, String?> =
+public fun ItemProvider.string(key: Name? = null): ReadOnlyProperty<Any?, String?> =
     item(key).convert(MetaConverter.string)
 
-fun ItemProvider.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> =
+public fun ItemProvider.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> =
     item(key).convert(MetaConverter.boolean)
 
-fun ItemProvider.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> =
+public fun ItemProvider.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> =
     item(key).convert(MetaConverter.number)
 
-fun ItemProvider.double(key: Name? = null): ReadOnlyProperty<Any?, Double?> =
+public fun ItemProvider.double(key: Name? = null): ReadOnlyProperty<Any?, Double?> =
     item(key).convert(MetaConverter.double)
 
-fun ItemProvider.float(key: Name? = null): ReadOnlyProperty<Any?, Float?> =
+public fun ItemProvider.float(key: Name? = null): ReadOnlyProperty<Any?, Float?> =
     item(key).convert(MetaConverter.float)
 
-fun ItemProvider.int(key: Name? = null): ReadOnlyProperty<Any?, Int?> =
+public fun ItemProvider.int(key: Name? = null): ReadOnlyProperty<Any?, Int?> =
     item(key).convert(MetaConverter.int)
 
-fun ItemProvider.long(key: Name? = null): ReadOnlyProperty<Any?, Long?> =
+public fun ItemProvider.long(key: Name? = null): ReadOnlyProperty<Any?, Long?> =
     item(key).convert(MetaConverter.long)
 
-fun ItemProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
+public fun ItemProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
     item(key).convert(MetaConverter.meta)
 
-fun ItemProvider.string(default: String, key: Name? = null): ReadOnlyProperty<Any?, String> =
+public fun ItemProvider.string(default: String, key: Name? = null): ReadOnlyProperty<Any?, String> =
     item(key).convert(MetaConverter.string) { default }
 
-fun ItemProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<Any?, Boolean> =
+public fun ItemProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<Any?, Boolean> =
     item(key).convert(MetaConverter.boolean) { default }
 
-fun ItemProvider.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> =
+public fun ItemProvider.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> =
     item(key).convert(MetaConverter.number) { default }
 
-fun ItemProvider.double(default: Double, key: Name? = null): ReadOnlyProperty<Any?, Double> =
+public fun ItemProvider.double(default: Double, key: Name? = null): ReadOnlyProperty<Any?, Double> =
     item(key).convert(MetaConverter.double) { default }
 
-fun ItemProvider.float(default: Float, key: Name? = null): ReadOnlyProperty<Any?, Float> =
+public fun ItemProvider.float(default: Float, key: Name? = null): ReadOnlyProperty<Any?, Float> =
     item(key).convert(MetaConverter.float) { default }
 
-fun ItemProvider.int(default: Int, key: Name? = null): ReadOnlyProperty<Any?, Int> =
+public fun ItemProvider.int(default: Int, key: Name? = null): ReadOnlyProperty<Any?, Int> =
     item(key).convert(MetaConverter.int) { default }
 
-fun ItemProvider.long(default: Long, key: Name? = null): ReadOnlyProperty<Any?, Long> =
+public fun ItemProvider.long(default: Long, key: Name? = null): ReadOnlyProperty<Any?, Long> =
     item(key).convert(MetaConverter.long) { default }
 
-inline fun <reified E : Enum<E>> ItemProvider.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> =
+public inline fun <reified E : Enum<E>> ItemProvider.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> =
     item(key).convert(MetaConverter.enum()) { default }
 
-fun ItemProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty<Any?, String> =
+public fun ItemProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty<Any?, String> =
     item(key).convert(MetaConverter.string, default)
 
-fun ItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty<Any?, Boolean> =
+public fun ItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty<Any?, Boolean> =
     item(key).convert(MetaConverter.boolean, default)
 
-fun ItemProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty<Any?, Number> =
+public fun ItemProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty<Any?, Number> =
     item(key).convert(MetaConverter.number, default)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
index 582890cf..debd05c8 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
@@ -15,7 +15,7 @@ import kotlinx.serialization.json.*
 /**
  * @param descriptor reserved for custom serialization in future
  */
-fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement {
+public fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement {
     return if (isList()) {
         JsonArray(list.map { it.toJson() })
     } else {
@@ -82,11 +82,11 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
     return JsonObject(elementMap)
 }
 
-fun Meta.toJson(descriptor: NodeDescriptor? = null): JsonObject = toJsonWithIndex(descriptor, null)
+public fun Meta.toJson(descriptor: NodeDescriptor? = null): JsonObject = toJsonWithIndex(descriptor, null)
 
-fun JsonObject.toMeta(descriptor: NodeDescriptor? = null): JsonMeta = JsonMeta(this, descriptor)
+public fun JsonObject.toMeta(descriptor: NodeDescriptor? = null): JsonMeta = JsonMeta(this, descriptor)
 
-fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
+public fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
     return when (this) {
         JsonNull -> Null
         else -> {
@@ -99,7 +99,7 @@ fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
     }
 }
 
-fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMeta> = when (this) {
+public fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMeta> = when (this) {
     is JsonPrimitive -> {
         val value = this.toValue(descriptor as? ValueDescriptor)
         MetaItem.ValueItem(value)
@@ -129,7 +129,7 @@ fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMet
 /**
  * A meta wrapping json object
  */
-class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : MetaBase() {
+public class JsonMeta(private val json: JsonObject, private val descriptor: NodeDescriptor? = null) : MetaBase() {
 
     private fun buildItems(): Map<NameToken, MetaItem<JsonMeta>> {
         val map = LinkedHashMap<NameToken, MetaItem<JsonMeta>>()
@@ -173,10 +173,10 @@ class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : M
 
     override val items: Map<NameToken, MetaItem<JsonMeta>> by lazy(::buildItems)
 
-    companion object {
+    public companion object {
         /**
          * A key representing top-level json array of nodes, which could not be directly represented by a meta node
          */
-        const val JSON_ARRAY_KEY = "@jsonArray"
+        public const val JSON_ARRAY_KEY: String = "@jsonArray"
     }
 }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt
index 7dec0790..96f42b46 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt
@@ -7,9 +7,9 @@ import hep.dataforge.names.NameToken
  * A meta laminate consisting of multiple immutable meta layers. For mutable front layer, use [Scheme].
  * If [layers] list contains a [Laminate] it is flat-mapped.
  */
-class Laminate(layers: List<Meta>) : MetaBase() {
+public class Laminate(layers: List<Meta>) : MetaBase() {
 
-    val layers: List<Meta> = layers.flatMap {
+    public val layers: List<Meta> = layers.flatMap {
         if (it is Laminate) {
             it.layers
         } else {
@@ -17,7 +17,7 @@ class Laminate(layers: List<Meta>) : MetaBase() {
         }
     }
 
-    constructor(vararg layers: Meta?) : this(layers.filterNotNull())
+    public constructor(vararg layers: Meta?) : this(layers.filterNotNull())
 
     override val items: Map<NameToken, MetaItem<Meta>> by lazy {
         layers.map { it.items.keys }.flatten().associateWith { key ->
@@ -28,21 +28,21 @@ class Laminate(layers: List<Meta>) : MetaBase() {
     /**
      * Generate sealed meta using [mergeRule]
      */
-    fun merge(): SealedMeta {
+    public fun merge(): SealedMeta {
         val items = layers.map { it.items.keys }.flatten().associateWith { key ->
             layers.asSequence().map { it.items[key] }.filterNotNull().merge()
         }
         return SealedMeta(items)
     }
 
-    companion object {
+    public companion object {
 
         /**
          * The default rule which always uses the first found item in sequence alongside with its children.
          *
          * TODO add picture
          */
-        val replaceRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.first().seal() }
+        public val replaceRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.first().seal() }
 
         private fun Sequence<MetaItem<*>>.merge(): MetaItem<SealedMeta> {
             return when {
@@ -76,14 +76,14 @@ class Laminate(layers: List<Meta>) : MetaBase() {
          * The values a replaced but meta children are joined
          * TODO add picture
          */
-        val mergeRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.merge() }
+        public val mergeRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.merge() }
     }
 }
 
 /**
  * Performance optimized version of get method
  */
-fun Laminate.getFirst(name: Name): MetaItem<*>? {
+public fun Laminate.getFirst(name: Name): MetaItem<*>? {
     layers.forEach { layer ->
         layer[name]?.let { return it }
     }
@@ -93,11 +93,11 @@ fun Laminate.getFirst(name: Name): MetaItem<*>? {
 /**
  * Create a new [Laminate] adding given layer to the top
  */
-fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
+public fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
 
 /**
  * Create a new [Laminate] adding given layer to the bottom
  */
-fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
+public fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
 
 //TODO add custom rules for Laminate merge
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
index 25d89860..fdbdab72 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
@@ -5,6 +5,7 @@ import hep.dataforge.meta.MetaItem.NodeItem
 import hep.dataforge.meta.MetaItem.ValueItem
 import hep.dataforge.names.*
 import hep.dataforge.values.*
+import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.Serializer
@@ -19,18 +20,19 @@ import kotlinx.serialization.encoding.Encoder
  * * a [NodeItem] (node)
  */
 @Serializable
-sealed class MetaItem<out M : Meta> {
+public sealed class MetaItem<out M : Meta> {
 
     abstract override fun equals(other: Any?): Boolean
 
     abstract override fun hashCode(): Int
 
     @Serializable
-    class ValueItem(val value: Value) : MetaItem<Nothing>() {
+    public class ValueItem(public val value: Value) : MetaItem<Nothing>() {
         override fun toString(): String = value.toString()
 
+        @OptIn(ExperimentalSerializationApi::class)
         @Serializer(ValueItem::class)
-        companion object : KSerializer<ValueItem> {
+        public companion object : KSerializer<ValueItem> {
             override val descriptor: SerialDescriptor get() = ValueSerializer.descriptor
 
             override fun deserialize(decoder: Decoder): ValueItem = ValueItem(ValueSerializer.deserialize(decoder))
@@ -50,12 +52,13 @@ sealed class MetaItem<out M : Meta> {
     }
 
     @Serializable
-    class NodeItem<M : Meta>(@Serializable(MetaSerializer::class) val node: M) : MetaItem<M>() {
+    public class NodeItem<M : Meta>(@Serializable(MetaSerializer::class) public val node: M) : MetaItem<M>() {
         //Fixing serializer for node could cause class cast problems, but it should not since Meta descendants are not serializeable
         override fun toString(): String = node.toString()
 
+        @OptIn(ExperimentalSerializationApi::class)
         @Serializer(NodeItem::class)
-        companion object : KSerializer<NodeItem<out Meta>> {
+        public companion object : KSerializer<NodeItem<out Meta>> {
             override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
 
             override fun deserialize(decoder: Decoder): NodeItem<*> = NodeItem(MetaSerializer.deserialize(decoder))
@@ -70,8 +73,8 @@ sealed class MetaItem<out M : Meta> {
         override fun hashCode(): Int = node.hashCode()
     }
 
-    companion object {
-        fun of(arg: Any?): MetaItem<*> {
+    public companion object {
+        public fun of(arg: Any?): MetaItem<*> {
             return when (arg) {
                 null -> ValueItem(Null)
                 is MetaItem<*> -> arg
@@ -82,19 +85,19 @@ sealed class MetaItem<out M : Meta> {
     }
 }
 
-fun Value.asMetaItem() = ValueItem(this)
-fun <M:Meta> M.asMetaItem() = NodeItem(this)
+public fun Value.asMetaItem(): ValueItem = ValueItem(this)
+public fun <M:Meta> M.asMetaItem(): NodeItem<M> = NodeItem(this)
 
 /**
  * The object that could be represented as [Meta]. Meta provided by [toMeta] method should fully represent object state.
  * Meaning that two states with the same meta are equal.
  */
-interface MetaRepr {
-    fun toMeta(): Meta
+public interface MetaRepr {
+    public fun toMeta(): Meta
 }
 
-interface ItemProvider{
-    fun getItem(name: Name): MetaItem<*>?
+public interface ItemProvider{
+    public fun getItem(name: Name): MetaItem<*>?
 }
 
 /**
@@ -104,11 +107,11 @@ interface ItemProvider{
  *
  *   * Same name siblings are supported via elements with the same [Name] but different queries
  */
-interface Meta : MetaRepr, ItemProvider {
+public interface Meta : MetaRepr, ItemProvider {
     /**
      * Top level items of meta tree
      */
-    val items: Map<NameToken, MetaItem<*>>
+    public val items: Map<NameToken, MetaItem<*>>
 
     override fun getItem(name: Name): MetaItem<*>? {
         if (name.isEmpty()) return NodeItem(this)
@@ -129,15 +132,15 @@ interface Meta : MetaRepr, ItemProvider {
 
     override fun toString(): String
 
-    companion object {
-        const val TYPE = "meta"
+    public companion object {
+        public const val TYPE: String = "meta"
 
         /**
          * A key for single value node
          */
-        const val VALUE_KEY = "@value"
+        public const val VALUE_KEY: String = "@value"
 
-        val EMPTY: Meta = object: MetaBase() {
+        public val EMPTY: Meta = object: MetaBase() {
             override val items: Map<NameToken, MetaItem<*>> = emptyMap()
         }
     }
@@ -150,19 +153,19 @@ interface Meta : MetaRepr, ItemProvider {
  *
  * If [name] is empty return current [Meta] as a [NodeItem]
  */
-operator fun Meta?.get(name: Name): MetaItem<*>? = this?.getItem(name)
+public operator fun Meta?.get(name: Name): MetaItem<*>? = this?.getItem(name)
 
-operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
+public operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
 
 /**
  * Parse [Name] from [key] using full name notation and pass it to [Meta.get]
  */
-operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
+public operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
 
 /**
  * Get a sequence of [Name]-[Value] pairs
  */
-fun Meta.values(): Sequence<Pair<Name, Value>> {
+public fun Meta.values(): Sequence<Pair<Name, Value>> {
     return items.asSequence().flatMap { (key, item) ->
         when (item) {
             is ValueItem -> sequenceOf(key.asName() to item.value)
@@ -174,7 +177,7 @@ fun Meta.values(): Sequence<Pair<Name, Value>> {
 /**
  * Get a sequence of all [Name]-[MetaItem] pairs for all items including nodes
  */
-fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
+public fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
     return sequence {
         items.forEach { (key, item) ->
             yield(key.asName() to item)
@@ -187,33 +190,33 @@ fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
     }
 }
 
-operator fun Meta.iterator(): Iterator<Pair<Name, MetaItem<*>>> = sequence().iterator()
+public operator fun Meta.iterator(): Iterator<Pair<Name, MetaItem<*>>> = sequence().iterator()
 
 /**
  * A meta node that ensures that all of its descendants has at least the same type
  */
-interface MetaNode<out M : MetaNode<M>> : Meta {
+public interface MetaNode<out M : MetaNode<M>> : Meta {
     override val items: Map<NameToken, MetaItem<M>>
 }
 
 /**
  * The same as [Meta.get], but with specific node type
  */
-operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? = if( this == null) {
+public operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? = if( this == null) {
     null
 } else {
     @Suppress("UNCHECKED_CAST", "ReplaceGetOrSet")
     (this as Meta).get(name) as MetaItem<M>? // Do not change
 }
 
-operator fun <M : MetaNode<M>> M?.get(key: String): MetaItem<M>? = this[key.toName()]
+public operator fun <M : MetaNode<M>> M?.get(key: String): MetaItem<M>? = this[key.toName()]
 
-operator fun <M : MetaNode<M>> M?.get(key: NameToken): MetaItem<M>? = this[key.asName()]
+public operator fun <M : MetaNode<M>> M?.get(key: NameToken): MetaItem<M>? = this[key.asName()]
 
 /**
  * Equals, hashcode and to string for any meta
  */
-abstract class MetaBase : Meta {
+public abstract class MetaBase : Meta {
 
     override fun equals(other: Any?): Boolean = if (other is Meta) {
         this.items == other.items
@@ -229,24 +232,24 @@ abstract class MetaBase : Meta {
 /**
  * Equals and hash code implementation for meta node
  */
-abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M>, MetaBase()
+public abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M>, MetaBase()
 
 /**
  * The meta implementation which is guaranteed to be immutable.
  *
  * If the argument is possibly mutable node, it is copied on creation
  */
-class SealedMeta internal constructor(
+public class SealedMeta internal constructor(
     override val items: Map<NameToken, MetaItem<SealedMeta>>
 ) : AbstractMetaNode<SealedMeta>()
 
 /**
  * Generate sealed node from [this]. If it is already sealed return it as is
  */
-fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(items.mapValues { entry -> entry.value.seal() })
+public fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(items.mapValues { entry -> entry.value.seal() })
 
 @Suppress("UNCHECKED_CAST")
-fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
+public fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
     is ValueItem -> this
     is NodeItem -> NodeItem(node.seal())
 }
@@ -254,32 +257,32 @@ fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
 /**
  * Unsafe methods to access values and nodes directly from [MetaItem]
  */
-val MetaItem<*>?.value: Value?
+public val MetaItem<*>?.value: Value?
     get() = (this as? ValueItem)?.value
         ?: (this?.node?.get(VALUE_KEY) as? ValueItem)?.value
 
-val MetaItem<*>?.string get() = value?.string
-val MetaItem<*>?.boolean get() = value?.boolean
-val MetaItem<*>?.number get() = value?.number
-val MetaItem<*>?.double get() = number?.toDouble()
-val MetaItem<*>?.float get() = number?.toFloat()
-val MetaItem<*>?.int get() = number?.toInt()
-val MetaItem<*>?.long get() = number?.toLong()
-val MetaItem<*>?.short get() = number?.toShort()
+public val MetaItem<*>?.string: String? get() = value?.string
+public val MetaItem<*>?.boolean: Boolean? get() = value?.boolean
+public val MetaItem<*>?.number: Number? get() = value?.number
+public val MetaItem<*>?.double: Double? get() = number?.toDouble()
+public val MetaItem<*>?.float: Float? get() = number?.toFloat()
+public val MetaItem<*>?.int: Int? get() = number?.toInt()
+public val MetaItem<*>?.long: Long? get() = number?.toLong()
+public val MetaItem<*>?.short: Short? get() = number?.toShort()
 
-inline fun <reified E : Enum<E>> MetaItem<*>?.enum(): E? = if (this is ValueItem && this.value is EnumValue<*>) {
+public inline fun <reified E : Enum<E>> MetaItem<*>?.enum(): E? = if (this is ValueItem && this.value is EnumValue<*>) {
     this.value.value as E
 } else {
     string?.let { enumValueOf<E>(it) }
 }
 
-val MetaItem<*>.stringList get() = value?.list?.map { it.string }
+public val MetaItem<*>.stringList: List<String>? get() = value?.list?.map { it.string }
 
-val <M : Meta> MetaItem<M>?.node: M?
+public val <M : Meta> MetaItem<M>?.node: M?
     get() = when (this) {
         null -> null
         is ValueItem -> null//error("Trying to interpret value meta item as node item")
         is NodeItem -> node
     }
 
-fun Meta.isEmpty() = this === Meta.EMPTY || this.items.isEmpty()
\ No newline at end of file
+public fun Meta.isEmpty(): Boolean = this === Meta.EMPTY || this.items.isEmpty()
\ No newline at end of file
diff --git a/dataforge-scripting/build.gradle.kts b/dataforge-scripting/build.gradle.kts
index 16ab6559..9eb40708 100644
--- a/dataforge-scripting/build.gradle.kts
+++ b/dataforge-scripting/build.gradle.kts
@@ -4,19 +4,19 @@ plugins {
 
 kotlin {
     sourceSets {
-        val commonMain by getting {
+        commonMain {
             dependencies {
                 api(project(":dataforge-workspace"))
                 implementation(kotlin("scripting-common"))
             }
         }
-        val jvmMain by getting {
+        jvmMain{
             dependencies {
                 implementation(kotlin("scripting-jvm-host"))
                 implementation(kotlin("scripting-jvm"))
             }
         }
-        val jvmTest by getting {
+        jvmTest {
             dependencies {
                 implementation("ch.qos.logback:logback-classic:1.2.3")
             }
diff --git a/dataforge-scripting/src/commonMain/kotlin/hep/dataforge/scripting/Placeholder.kt b/dataforge-scripting/src/commonMain/kotlin/hep/dataforge/scripting/Placeholder.kt
deleted file mode 100644
index a09e35c1..00000000
--- a/dataforge-scripting/src/commonMain/kotlin/hep/dataforge/scripting/Placeholder.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package hep.dataforge.scripting
-
-internal object Placeholder {
-}
\ No newline at end of file
diff --git a/dataforge-scripting/src/jvmMain/kotlin/hep/dataforge/scripting/Builders.kt b/dataforge-scripting/src/jvmMain/kotlin/hep/dataforge/scripting/Builders.kt
index 2df5a183..e8b1d378 100644
--- a/dataforge-scripting/src/jvmMain/kotlin/hep/dataforge/scripting/Builders.kt
+++ b/dataforge-scripting/src/jvmMain/kotlin/hep/dataforge/scripting/Builders.kt
@@ -13,15 +13,18 @@ import kotlin.script.experimental.jvm.dependenciesFromCurrentContext
 import kotlin.script.experimental.jvm.jvm
 import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
 
-object Builders {
+public object Builders {
 
-    fun buildWorkspace(source: SourceCode, context: Context = Global): Workspace {
+    private fun buildWorkspace(source: SourceCode, context: Context = Global): Workspace {
         val builder = SimpleWorkspaceBuilder(context)
 
         val workspaceScriptConfiguration = ScriptCompilationConfiguration {
-            baseClass(Any::class)
+//            baseClass(Any::class)
             implicitReceivers(WorkspaceBuilder::class)
-            defaultImports("hep.dataforge.workspace.*")
+            defaultImports(
+                "hep.dataforge.meta.*",
+                "hep.dataforge.workspace.*"
+            )
             jvm {
                 dependenciesFromCurrentContext(wholeClasspath = true)
             }
@@ -49,7 +52,7 @@ object Builders {
         return builder.build()
     }
 
-    fun buildWorkspace(file: File): Workspace = buildWorkspace(file.toScriptSource())
+    public fun buildWorkspace(file: File): Workspace = buildWorkspace(file.toScriptSource())
 
-    fun buildWorkspace(string: String): Workspace = buildWorkspace(string.toScriptSource())
+    public fun buildWorkspace(string: String): Workspace = buildWorkspace(string.toScriptSource())
 }
\ No newline at end of file
diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts
index 5d745ff8..0c1972cd 100644
--- a/dataforge-workspace/build.gradle.kts
+++ b/dataforge-workspace/build.gradle.kts
@@ -4,7 +4,7 @@ plugins {
 
 kotlin {
     sourceSets {
-        val commonMain by getting{
+        commonMain{
             dependencies {
                 api(project(":dataforge-context"))
                 api(project(":dataforge-data"))
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 62d4c053550b91381bbd28b1afc82d634bf73a8a..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644
GIT binary patch
delta 6656
zcmY+Ibx_pN*Z*PZ4(U#j1qtbvrOTyO8fghZ8kYJfEe%U|$dV!@ASKczEZq$fg48M@
z;LnHO_j#Uq?%bL4dY^md%$$4Y+&@nKC|1uHR&59YNhubGh72|a#ylPdh9V+akp|I;
zPk^W-a00GrFMkz_NSADdv2G2-i6rb=cB_@WnG(**4ZO$=96R=t|NZ@|0_z&q3GwO^
ziUFcuj$a9QaZ3j?xt`5#q`sT-ufrtBP0nt3IA&dr*+VCsBzBVW?vZ6eZr0oD%t33z
zm~-5IVsjy(F>;S~Pm@bxX85>Z*@(QL6i3JQc?1ryQFcC@X<g1opq2_}qf2n}bDuZ!
zWKPTwxVBuNP19Vh!S06D1kwi8IR?%Q_tS6CMlcH1GHnzzTF6L#bC>^2^mZWhFv|v?
z49>l|nA&XNQ6#OvccUTyBMB*WO#NA;FW5|eE_K6dtVYP2G?uUZ09!`Iq1IF2gA(aS
zLu@G^cQJmh=x?-YsYa@E6QnE5+1@ds&0f#OQRDl^GnIT_m84G5<dL|9;ap-%@DK)Z
zJXsEXvC4R9p`vBWj#UC!X4t9*FN2~aT(@1kpVpb4hs(&XgSwrc&@$a1G{BRj>XY%W
z;Ck6bk^Oeu*Ma-XmxI5GjqzWNbJMsQF4)WfMZEA{oxW0E32e)*JfG}3otPishIQBw
zkBe6N#4pKPN>q1<c_S*OgJu!sX3Z+i&!nPIcOY>R6G1@5&(u#5yPEToMBB6_oEK|q
z@(i5j!?;NNCv~=HvW%zF&1yWBq(nJa_#``G&SRmQvE|jePUPs{J!$TacM|e}Fsceb
zx+76|mDp6@w>)^DIl{8?)6XYNRU|2plG8Jy&7(^9SdOWNKKJK&>0!z6XiN4J*Jkao
z=E1y5x-XDC==Ub+8fLb#OW&{2ww{h^xlJFYAMOUd)}Xg@j?ak{7Kno6?9S~F?|6Df
zHo|ijXX~`Sp;Vf!nR;m%vUhq>zvlRXsL0u*Tt?F#yR}3tF0#of{(UjitqST|!{aBA
zicWh+URU}Jnc*sg9iMkf0pggpd?3TI*C-q<w(&M(m~}<+ea%u!x4kn@vQlH&LiI*R
zB7X4OuQk^>$2QOdCC7rV+CHBmjS3O%a3VeZ$ZSs5ubJuJp%e%$LHgrj0niYjX;4kt
z&2~j%@q3MO)-QGCA{>o%eZu){ou^MgC6~Z8Y=tc!qF=|TOlG3wJXbaLYr-;$Ch=2J
z_UcE59Xzq&h0LsjLrcZrQSa}#=<pCCwP+K`qAyWcDPE8l5gLuQQOCvX;roV=GVrSE
zRN);#vB=RiA;a;S-a3{ts<IR~#XeBK(^k2SU^wSX*pR6ItHBeZh6`9>0~Lk|4?e4M
z6d;v->NCC1oMti)RRc`Ys0?JXQjsZ@VdCy%Z)TptCrI>0Tte$pR!@yJesoU2dtyuW
z7iFsE8)CkbiJP+OP28;(%?!9WddQZcAid@R@`*e%3W65$g9ee`zvwb(VPO+uVBq6p
z{QDR%CR(2z@?&9Obm3xPi2lzvfip`7q`_7UDD|lRS}4=bsl3xQIOi0@GSvMuDQX}*
z4B^(DI<${qUhcLqO`itJU;e<%%iS+R3I^_xIV1O%sp*x~;-dn`<aYhWZu1&;ElKY}
zZm_NJ1y%e}JjMBfENCOnH*9mb%EUJ6T{;w?3xbxNE?0r$=$2S(JXNNaff+pj)0X3>
zt$8>RnSUh#rU3{-47067W^WNwTdq-t$-U>Hj%<yt<n{U-FV<(AG&gDIp@t66wM-#N
zJ0?<X`&{ENL@S2=a5R+rxyBKhousp3mE<6*BMfnp%7NjFkWa)L3fT`1HBv5%ZfmOw
zhfZB1(`R?=E{3p6h;?}T;`D(_q#Ku3P-Ts<H#|7m=*&#2oY&#Ro7~>r!GD!gLa;kV
zW5g6pCqV+!q8L<UGl1?nMLH9G$%I9J5pf%SH`n0VUkU3HRVup}<-k>g<GGq)5g+Yh
z(D%0Fi%@DB?*x0Zd<NwfgyV{8`bVpQShO;~J|KWnPzdo^lb#dD?*K6EooR1<VJ_v<
zIDNbrd-Z5*%cthuAR2mSEPE16Kl1(GUID!8pTq5|-JJ!w8cUSAz)I_XJ9(9qPII5A
z{m8ntai8GtO_h-1);fteB7SYUuxchvIWXzRs-%D3CKzg49@qap!-y_GAiFu7J2<V+
zI9$85dJyuc!h2k|X8>rI49(}fIc5K_`FLV4_E#XZ6{<>w8wzc%V9k!!Byg5-0W<bB
zR4jcLpMe)Gr+Qyft>Y+J?1*z%9~Aj4WQr1Jsn2(G!U8fFpi(wsy@JLg^d+IB0kl89
z0@Ssqf!L9JjYKK$J=978+NO*5^C)GPH2a%4hm$HROjM|N3g9ch9kDLh*nlwqy{mVM
z`P(l#>3NnK%#O8tSb(VmZrG+`dRD#=Cc1P%(y5<uj@qeNQCeA+H|Gn!g_|!%1V&w&
zuh#8(%DbZdv0kum$}C@EvW671;^A-6ZeF^cq90@k<+emVi}AFjw0JMveLbO*9WV0O
z&|{@C`c`onN9UkF9-_#}<r?8uJJmMfj{j(TBRk{Sx^)QATI}<bZ@pbg#5I&#ETmpi
zdutUe8}E>S?*Hj5E{vg&Eiw!YV>S#7_WRDVoFxT5m=gFi4)}y5V%KT8!xbsH_rmR&
zsmM?%J}K$1l8d?2+m(}2c}-G`x>CY%Y&QBJRC$sKM}zN<9{IlF@yJEG<^0={$+`Hc
zDodJ)gCADJ_bD#am(c2ojXKb|j+ENJ#58PAA&pZXufrFzBwnuuo+khfMgd!DMlU#v
z9|JelQO~E2;d^w!RZJbt%IANIudpKSP)cssoWhq)>({nvcfCr0=9=FAIMuZm8Eo=}
z|DND}8_PB5HqG(QwDvaM@orYBZ9kCkHV*<E7fD~^kv%Rt4%{0-C)!*WD4&mmZ)2k@
z-vh9{wcc~riJLaZRf=zb|DG1QfaO{cxPCox1C=uT`?QobU{6i7M5tnvWwDprp6hO!
z9Olm3CW}@PFjzRUj)1AJdn)o8&6l`GL^Vw`8_u3=Yfczem_N=JgXn+gw#@t%tK48L
zs-<kelU-VD@{pmRdxYAu=uDIBXxH>rxKTy>q7n~0emErUwLbhq;VN<2nKT&*a2Ajz
z;lKBzU2i8KLV`d)Y&ae)!HcGk$dO}Or%8KF@kE@jU1h@zwpw{6p4ME|uC$Za-ERR2
ztQvL&uOZLe(k{w_+J^ng+l}~N8MP>F1Z$fLu}D-WWaeu#XduP@#8JpmH(X>rIL)k3
zyXN<rev&d&<2WhaHMotlzr4K)q{=z;9yuB}>yTIB1(IH%S&pQ{rWaTVfB$~-;RnlY
z^(y7mR>@=brI>!TrA)BQsQ={b*6$=1Eqbuu6IdhJ&$YD$08AwtNr9*J?%-WT<;O1<
zPl1<@yeqfZ>@s4azqTf<=I4(kU^+^Qkstm%WM-0_VLm({jFc8`5Df2Q1Y9zMZu0^!
zsO_yh2Sz9K>Jq6fkYbBZocEJ6C!SdEzYDki<UOQeTxqpjlE|pdf{rBSqZixK7JCQ3
za};>EtNJs{?!tA#e|oiN+VaaAobwKef_kUup&4scD?1+}Q8)DaekkMYn-FOS{J%NY
za^mmJ^n`t*1p@hF*gl#L+5wr40*(ub4J#L|@oCl~@|4UvCjHBYDQ<!vXtmSW&BzM&
zXCI8YO-Gl|ywfX4W|TNg|9V$g!tLC2nAlHTp*X=wVa=dll|;=;C!FFd`g5-mY#xif
zCrc|%X+s(7QZF6mu~fSmKun~s(X%MyENK#tU+^qGE_(Wr)GBG;=``T~g*~piR>v&S
zhyGMAkRO^tF_dyi&XM)4mQ;k>kj?Rg<j^$zwJ$9puUmM8UTsnl8o98aL@#eUk2T@Z
zqrD)t_0=dw*ucUqtb<o3xt;=7iFLqRgUUI5+ac`qMuWQ|kuL1{tAxL;i&U#0PcS3M
zz)XghN!?Liqk700FA&h+RC8`bO%6eLm?;=pd1*#hD4`dB*@?<Zh=@~@+ywEwqdE!q
zvgJyQHWiY$0fC@DG;IIOj`<tUPDWmHNSP9Ub5<phX&5{ZKNNnzZka#ulAcr8(Pe1#
z?F$huuXLj!;t!DOL%CownzwD5sHR`0d9Bp3gf-l7^DCB=I2quKZskc8$|SoP!V#2_
z`*g51(;1U&!%(|9{%bDJEKTC`ji%DwO-jZY?C@uqG`?Gp$$3WJI(Y=^5wIvSKG~%3
z@HVu=CGDCWd$!}~CX)4b(^Di1y6h66Cz_v>Ro@-?==oD+ns*>bf@&fPXF|4U0&ib2
zo~1ZdmCPWf!W9#sGP@9X$;Rc`tjbz^&JY}z{}j9bl?;VC{x)TfQH$D^WowKL&4Zx@
zdSn+QV7H(e0xRfN6aBfH)Q=@weoD?dvu6^ZS)zqb>GwMmIuS8zJfaMUQx9>%k~w34
z3}_B2Jj~u=SnJ~vZPj*)UoDi_FtT=UAb#J^b4B%R6z3H%cj-1OCjU5F$ky>By1zsg
z>2A0ccp29(Y<;my|J_g-r{1I@+*O$>!R3`_sFNP4e}LD1e1mM&SA`;;TR0I`_hESV
zh4U*9ecK$0=lYk`{SR_cm$}iS*?yQR(}T-5ub?Wn^#RTe*^1~y<L@mmwlq4SqQ^?7
zf7HAsMJ5k`W|1diAqpM5uUc8t@?WSh02mK$-Z;uXYCkL7ljF*c65*4_UK4l|`X<eU
z^N$DksrBl1@$Dq}7uV|tt!bh+5FU%NxvXKkJEx$0R%>a%`!xWq-F*WH@%nnZTNREA
z3eUX2uM9b_w!Zo$nVTotEtzuL(88N)H~v_G=89|(@IFz~Wq6ME);z(!2^PkR2B&kE
zxR)xV8PE|Hszyjp#jNf=ZIQ7JR~4Ls#Vd@mPF(7R5VO$akUq8JM+sn>ZVg<OsE?Y=
zt3-TLl#CZV8ORMEf6*q;Tnxr)!*Y1IoRA-M0=p!LFW64(0m88U<oG$?P$^h+WmvS9
z<8z1rS2(}S*O&eI-K7~4v48J3xj`QiGpU_a%TBpGAh&v{?J_XalWixRT<}`uCL0Y^
zKB~jnq|v$FLLNbplmri)IYLkmF%#~TlvYmKBn(<H%e+PW4UN<fy-v)zu0$9B2*z9N
zy)F~H8nKt#UG6>(lJZ)5qjqdw(*7tuwjY#0tx+|!sTz9yV~%HOdrb#!5w9>*0LrCS
z%wF$Yc6~hqVQZzoC^D<(-h0aOtk}kn<<*x<A9mKbP59xJ&kBtE?yc}h?x49=29=z5
z7U|zFE0ulr4;2`B6lrT?x-kUP7ZGRtFHk!A!-sdf?I?Ik<PlR?wDIbv!Z*<2aw=!Q
zhp0EM%B4Q)?vQ#>F61HQr<5}efY{zXXA+PaJG7vT&{Oz(@Uu!V#Fp9%Ht!~@;6AcD
z$lvlPu&yd(YnAHfpN51*<LyqPo5!UzBh2tI#n2^qu<jx|_m5<z4nj-b!Mswq8*jU5
zY#>)JN0aYw9gGk{NE7!O<M2UZbF4L>qu4rBp}F30669;{zcH-a7w9KSpDQPIE_f9T
zit<e72SXx52%a0m4sGH(B<|=w6Y(ybW4-qB1uqEWI&~veyng0KkrFJ}KX^W^s?U3(
zs2i~8*TWIIbmEyPwvm}db!=_(gmmKD@xJOY(~YawWggKL<fbxDMw@}=8IlRmRv$>?
zJSjTKWbe{f{9BmSDAFO1(K0oqB4578tU<q-Ne=5=n^YUvA(1)FPw|uIz68u3R{NH`
zK^uEMleb&(=C`d@mZz8w`l4ZDh7>0(oRBE^28X>xDA!1C&VJEiYak4_ZTM*7M`hv_
zw3;2ndv3X$zT!wa7TrId{gNE`Vxf}j5wsyX+;Kn<^$EJT`NzznjyYx=pYMkZjizEU
zb;Gg8Pl_pqxg)9P)C)Hxh_-mQ;u-I_Ol>d^>q08zFF!>Z3j1-HmuME_TGZ*Ev;O0O
z%e(edJfV<6t3&FKwtInnj9EeQhq9;o5oLJoiKwWF5bP2~Feh#P4oN()JT0pdq!9x*
ze3D-1%AV#{G=Op$6q?*Z>s{qFn}cl@9#m@DK_Bs@fdwSN`Qe18_WnveRB583mdMG-
z?<3pJC!YljOnO8=M=|Cg)jw;4>4sna`uI>Kh&F20jNOk9HX&}Ry|mHJ+?emHnbYLJ
zwfkx@slh31+3nq-9G5FVDQBHWWY}&hJ-fpDf!lQdmw8dlTt#=)20X74S>c&kR(?PT
zBg)Y%)q&|hW1K;`nJPAGF*c3{3`FvrhD9=Ld{3M*K&5$jRhXNsq$0CLXINax1AmXX
ziF39vkNtcK6i^+G^AEY!WalGazOQ$_#tx?BQ{YY$&V&42sICVl8@AI6yv;sGnT;@f
zL=}rZcJqNwrEEA=GDdEe8Z=f9>^?($oS8xGdFf1eUWTYtZF<3tu2V%noPBnd=thZ+
zO&xoc?jvXG7Xt!RTw#5VN50UjgqSntw9Y35*~pxz=8OzkXg{@S2J%+{l3Q>B_qbnl
z20Deb7JM&ZSp`%X>xWpb>FF8q7Nq&4#a1}A-(-!aMDmVbz05D!NpUzVe{~72h%cOh
zwQFNai2a$K<lb>|hFgDk(oPF_tuf{BV!=m0*xqSzGAJ(~XUh8rk#{YOg0ReK>4eJl
z;-~u5v$}DM)#vER>F)-}y(X6rGkp<{AkiPM7rFgAV^)FUX8XmCKKaWlS4;MSEagj$
z#pvH`vLX1q{&eOm>htnk4hmv=_)ao!MCp}9ql5yfre&Py!~hBAGNBa}PH&J8K=~<%
z&?!J-QaH|0bq_uo6rt*r-M>d7jm1cbW^T>s)S?L{<LgYs4$0}?XO8K~#{O6m2!CM0
z#Fo>n8v`^?VIPA+qi^6e@cM|5boqEO!p1e|_{7U3Yl6K?0xMN1bbjf0@$TE-T))w>
zFe?E?g$PUT-)AJ(PS^By^D^Ed!K5iv$*_eW<?$gk^ph*&Zkhdaw3i_v<GhJk|I!}L
zHQc`<CTEX!k2X24SiMt&T15AG1<E<Xmk*5-0d$t5VhMvaiUj$*^^Hdbo{kaE2oCn8
z{P^BVPxp~(2kY{iRU!^zTe}Wo#z|<Ai`g_yW$S+T2Im{GIGmFiK2shuu14CmOr}6Y
z=bVpR=^=4i>~VA(I3~UMy*ZcgVu0$XZC*_0PgDmUL)qTCn927LD~p$yXR_GCJ&iQ;
z4*`%l-dC5pALH!y*nmhdHRh02QjW1vZL4ySucz*w3f|#`=u@@YvMV1?i!&DIa2+S<
z8z!gvN3FV4I;%fl;ruFeV{jKjI~?GlgkmG<!$YWAS;7KYqqu1ud246Lh<veb9iZ`Y
zQshertU5W-2yEW32YKEq9B9NDHt!WC3}CB|^}1WeMrQ0g_ZKjQ=}R~Wbh!pQNl&h9
zA3+TUWpuB>BuJ<7vY|l3xMOc?S@Q#C(zo*m&JLrjT2rU9PYOniB8O~yO5<1CCcQz#
z17B2m1Z{R!Y)UO#CU-Y&mOlv4*Gz%rC_YkRcO)jTUEWHDvv!GWmEihE>OKPx1J?Av
z8J{-#7NsT>>R#*7**=QL)1@IR77G9JGZZiVt!=jD+i(oRV;I`JkiTSZkAXuHm-VG1
z+2-LD!!2dNEk@1@Rp|C$MD9mH^)H*G*wI(i*Rc6Vvdik+BDycYQ*=0JA3dxxha|Zg
zCIW1Ye-DdpMGTEwbA^6hVC<(@0FL4dkDOYcxxC5c%MJQ^)zpA%>>~Q|Y=@)XW!px;
z_Fx+xOo7>sz4QX|Ef~igE+uFnzFWP<-#||*V0`0p7E*+n5+awuOWmvR{-M*chIXgo
zYiZvQMond#{F8+4Zh_;>MsaZUuhp=onH@P!7W>sq|CWv|u}Wg0vo&f4UtmLzhCwwu
zJaR=IO;sQxS}h(K>9VZjnED+>9rGgB3ks+AwTy_EYH{oc)mo`451n&YH%A1@WC{;1
z<S^oOzaAWP#P5AQ+yVE{zDZxsAshHBu`Sn^2)=$8V4u{G7s4nfAql8C-&rsbhL619
zT{pccX^Z(hBgxhK7sr@H2<zfTupxqNt`Ymc=JN=v85hF;oxmYxW{jEs&)DGKi0;4F
z`?t{)h-7k3gy1|mB50NYRLPDgViQ4(%z{DL9EfCgF$Dh{7*xdjFNhl9I;RY>=fB6n
zIYp46_&u`COM&Di?$P}pPAlAF*Ss<)2Xc?=@_2|EMO?(A1u!Vc=-%bDAP#zDiYQvJ
z0}+}3GaLxsMIlh6?f=iRs0K=RyvMOcWl*xqe-IBLv?K{S^hP)@K|$I+h_)pdD9r~!
zxhw<f^+7<FEkIEJe}*3M!jB8_V;Ky>2u66+F(E`&6hY}B_qe>wil|#*0R0B;<@E?L
zVrhXKfwRg0l8r>LuNs1QqW&39ME0sOXe8zycivGVqUOjEWpU)h|9fwp@d(8=M-WxY
zeazSz6x5e`k821fgylLIbdqx~Kdh^Oj`Q!4v<MeLmQVBVlpLY7!2m)R{l`s%7~UjD
zl>c*Km)^Tr-qRxPHozdvvU^#xNsKVr6aw8={70&S4y*5xeoF@Q^y596*09`XF56-N
z1=Rm5?-An178o?$ix}y7gizQ9gEmGHF5AW+92DYaOcwEHnjAr~!vI>CK%h`E_tO8L
Yte!%o?r4GTrVtxD61Ym!|5fq-1K$0e!T<mO

delta 6475
zcmY+IbySpHyT)Mv(V?XWQEKQKx&;a8?rvs8N*ZBC(4modXq0Xc5Re7|2?eA<x?>1w
z1SC8j)_dObefzK9b=~*c&wBRW>;B{VGKiBofK!FMN5oJBE0V;;!kWUz!jc1W?5KdY
zyZ3<RNhmOMPXQ%?Y{f(mV$PR(&ta>mCBHprpchz-9{ASiJJh&&h1|4rdw6wxD2+9=
z#6#}Uq8&^1F3wgvGFoNDo?bIeEQXpcuAR0-+<E0eD1<+n495hAFD-m!{c9R+acsl`
zr2;WG>w$JWoK-@yUal1M&~W_O)r+Rx;{@hWH5n^oQWR36GMYBDDZyPK4L@WV<AWd8
z3jJ~Dx0Sn}6r@wK_EVL?e7(uHgF33t=)?1OWJsL`Y@B|w8<p8lug3^Cfo4)a?ys2~
zp$BnBOcfgbvy{}O$2FZ<Yc<4(^kd6-NxixHbx#di;*DLf{AN`{XPIV|p8XxJ%~6T9
z169SiFQ}4vKl<OXaQ$?J5=Smvsba&>jRrF+XlSzi4X4!_!U%Uujl6LHQ#|l(sUU%{
zefYd8jnVYP91K}Qn-OmmSLYFK1h~_}RPS~>+Xdz%dpvpJ{ll!IKX=JN99qowqslbO
zV3DmqPZ}6>KB!9>jEObpi$u5oGPfO3O5!o3N2Mn`ozpje<}1I1H)m2rJDcB7AwXc6
z6j)tnPiql7#)r+b+p9?MVahp&=qJ^$oG+a^C*);FoJ!+V*^W+|2Olx5{*&$bXth)U
zejc7mU6cBp?^Rj|dd{GL-0eHRTBi6_yJ&GLP5kIncv^z{?=0AVy^5{S8_n=rtua!J
zFGY=A(yV^ZhB}1J_y(F`3QTu+zkHlw;1GiFeP&pw0N1k%NShHlO(4W+(!wy5phcg4
zA-|}(lE_1@@e6y`veg;v7m;q%(PFG&K3#}eRhJioXUU0jg_8{kn$;KVwf;zpL2X_(
zC*_R#5*PaBaY73(x*oZ}oE#HPLJQRQ7brNK=v!lsu==lSG1(&q>F)`adBT~d*lMS|
z%!%7(p~<7kWNmpZ5-N31*e=8`kih|g5lVrI%2wnLF-2D+G4k6@F<j<_KKI2HUZ#JC
zEL?^UQ`790e!k%Sl`r$=7wv$)k+UD3#J7xkQm8|*_z_t&0&znDYdlFf<lSb9D@O@+
zZ!-`kEDk&T;jsyNIvu2?{5YHB@d_?dcUQM7ZCGTAXoZ7?vRUpVPB`DEb=&;WPjC34
zF+s`Jb*T<gJMUdgTFKxZ<#?~UldG&2rr!NcDw_QFOECs<wiAO?1xcTCUdWSFO{iDt
zii;4@b{2!gSVd*_;SD{Wj4bX4QwT~c`|aA0{<u{!?DGl@lKC>rYsJ_80AJ}KMRi>)
z-kIeHp{maorNWkF81v0FKgB==_6blyaF$5GaW)B!i4v*jNk6r)vU6?G$0pV8(Y+UK
z5lgRVt%;N_gWp)^osv=h+^07UY6+$4^#t=M3>0i0`{`aEkFLL#a)93uXhYO+aKTtu
zckg2T9S&GKNtZmdAS^8PzvDva-%-K&g9eqPXQ4$dM<HFq^W4I;ysVDth>^inr@6Zl
z{!Cq&C_+V;g*{>!0cZP}?ogDb$#ZS=n@NHE{>k@84lOkl&$Bt2NF)W%GClViJq14_
zQIfa^q+0aq){}CO8j%g%R9|;G0uJuND*HO$2i&U_uW_a5xJ33~(Vy?;%6_(2_Cuq1
zLhThN@xH7-BaNtkKTn^taQHrs$<<)euc6z(dhps>SM;^Wx=7;O&IfNVJq3wk4<1VS
z-`*7W4DR_i^W4=dRh>AXi~J$K>`UqP>CKVVH&+T(ODhRJZO7DScU$F7D)di-%^8?O
z6)Ux`zdrVOe1GN<G3RW<P}NclcZ;cr1<LFtG_;Z672#mvZgILXiTZvTpg(f1%=}tq
zw4t5+i@n~C;YWwxL5oy<J+Fl#54P_AVbyFP<o}isGa;mL7SC}s)k7Y-^2dTzes6p#
zt!v<GA#F7bwx;uCare`wDTh>kPo0FgrrxSu1AGQkJe@pqu}8LkBDm+V<Ga%|X~U@M
z(Y0q99Ga{NmNw0uagTIun{8R8q;oX}#>!N_1l}`tjLW8${rgDLv3m@E*#zappt-Mm
zSC<$o+6UO~w0C=(0$&*y**@nKe_Q{|eAuD!(0YL0_a{z%+sdfSyP={Nyd$re6Rzbp
zvsgTY7~VflX0^Vf7qqomYZ_$ryrFVV2$sFyzw2r%Q8*uYDA+)iQdfKms_5(>!s#!(
z!P5S(N0i9CKQKaqg(U%Gk#V3*?)lO6dLv`8KB~F<-%VhbtL8Rl>mEz+PN=qx&t*|=
zQHV=qG)YKlPk4iCyWIUGjC?kpeA>hIBK*A?B0)rB=RqAal#D%1C9yVQwBcz${#Jb5
zR{TRmMrOrJsLc&6x9qDo@FJ^=do_Y?3oU0G^nV5_EU&+DS+VA7Tp{^TAF>yZbyM3c
zf*1CqHY9T|aL_lyY7c)i!_MtGPA!sdy3|mrsKVj1mi&>dms@-ozSa}OZ?2I*tAndg
z@S7er$t^d^-;!wLQbG60nWd@1pQVD7tw-G_B#OscoYyremiZ_hj8*sXqQdchuD^!R
zpXGuSj5psk+jR>3rWu3^`17>j&*^9^rWbszP=Mf@5KIEj%b=z98v=Ymp%$FYt>%Ld
zm8})EDbNOJu9n)gwhz_RS``#Ag)fr)3<*?(!9O~mTQWeh;8c;0@o=iBLQNqx3d_<e
zt91v<?G?!LHz{R-87XfM!AWjL{sn#5a;-QI*9|NoYZIK6hoh(;ejoaFC@lGuPdVMR
z8|8A;z@h<-5g7)qWCEs?ZF<WwoNl@oyh);EEsE<OI(uB6T>2#W7S9#FXzr6VXfs>4
z;QXw}-STvK9_-7H=uqgal2{GkbjVLN+=D5ddd)4^WvX;(NYA*X*(JxTdiUzqVJopd
zQg#~psX4o<)cF>r=rxP`(Xsf<+HG-pf&7aFPL8z|-&B*<cG2l%Lne(g(X=5qY;sV4
z0>P?Vmsu5d>Nlg^2$WRY!S@#`g2{81;(1w#o5HsvN}5pFZi});>|VK^kL{Zkx~wgn
ztlZp;HW`H8(GdRfIwc~?#N6}o#h158ohI*GIsK%56I_9sf2k_K@4vD!l{(dX<T?g%
zrms1H&%vebw!Y=teDdj6F)p>9E7PJ;w>$|Y;-VBJSO4@){07bo-89^LZ9g<<%;dOl
zyIq{s8`8Ltp*GDwu(l_Z$6sA2nam$BM$Q~6TpZg)w2TtW?G5whV(lRwaf$6EU86is
zBP9Rs&vS_~sk?Nn_b}^HkM8LiO@>J}=g(T4hLmvH@5Jj#2aHa~K)lD9VB0k>$V2BP
zgh;(=y9Op(KQ=H5vj+%qs>?s4tYN~-Q|fyQePA)s?HrF~;l!+@t8VMzqUpqMLudFT
z)=o~s!MM4XkgbetIsODwtQ=FF$IcIp&!pjh6Q6{tL+l*7GQ%8Wsg(tC#qU3oW$~n)
zL=>XIxI}Hi7HS0F_mmi+(c%1HDuKiWm>|6Xa}nW7ei55ggru9)xjBvC#JcEIN*#cp
zv*ACvr=HTC?dX9NNo9Yhulu_gX5Z~}QQ2&<EDiSMXfaw20`D7%r8>QZ&C77{(>Y3_
z6j5Z1Uc5FtPEpS_31HsgmSLHZijGb_p$WlRJ1p^_1!ZLP8kr6OtCEK7Qh267o$H>e
zf<4cNGQRk{g5h$XfvTFQ@`qm@iju83-~}ebAYpZryARHV<pnnVl6HqVd-~eq0b|^~
zXL7TnPTpIFQmhSB)b5l4$^x!j)+b-fpP-ynI=~SJ^DjV*^0_=%QVOFU^CF=~nZ^bZ
zrrop2nQF?<^#Rg=p4uupt9UUJV)dwPHPr*~OjUe%WL}<tq&t>R$AEt3229U{y@Fp4
z-8FBBtGG&(hTyUdx5ZOfiz`<AI)VX7bEFpu1-x0P81b(b4oI{%xs+nB+aMa0MJcbn
zhP1w3C>c=<0F%+w|Fl=rWk{K7>70k04SN?RU(^mrKSeKDqA!K^Hsv8C?#ioj4@WUL
zC*?{hTai6q0%_oBTqDHygp_Kl;({sAScYQIwMDM<s-CCk#Y$G$Wso4i5>1U>{x0ww
zve?_}E;DG?+|zsUrsph5X_G7l#Y~vqkq3@NNDabbw7|`eJBmn`Qrlr%?`va<J3V69
zXb#O%!_wLU1y<Jv5qIB>=mm$Mc{+FBbQbogAZ6{MuzT|P%QZZotd21eb1h<lbjWII
zJ~Gos^_!Z+jS<>fj|;GYAX&>bx#D5EB+=XMj<r12P7cqm7+N`>2XJkpnyMUykaVo)
zj3ZLqEl1&)Rturc8m@<Ex6KZzS6`#!al~-4tE^uvTOyR(MQ~K+RcWzvfHqB0k580{
z)X{VLE6qZJFkh0BJ1@`hLUnDQUgG0l;@p?R=_ZBnYtb3XYPC;uFo)oX@xM-ZqOz9=
zw$`!EQV)}*KwEb!jfNDVpu>+uUuD^vaNaSxGwP4dq0-OSb~62lPv8E_K4usLvG{Qg
zdR%z8dd2H!{JaT|X_bfm{##*W$YM;_J8Y8&Z)*<JSI-Ur%}(kH3&2X}J>ImOAf4+|
zEyi)qK%Ld1bHuqD+}-WiCnjszDeC-%8g+8JRpG1bOc!xUGB?@?6f~FTrI%U#5R~YF
z%t5(S2Q>?0`(XNHa8xKdTEZ~Z4SJOheit#ldfdg63}#W6j8kO;SjQD`vftxS+#x1B
zYu|5szEvkyz|}|B3x|DNlyi$;+n+cW$Hu+?)=X1!sa%{H-^;oBO9XACZJ}wkQ!sTa
zQ#J3h|HX{{&WwIG3h7d6aWktuJaO)ie6&=KJBoX@w(rBWfin`*a6OmCC5M0HzL(gv
zY<*e4hmW>SWVhxk-`UGOAbD%Hk+uu<^7zJ_ytVXamfqCd0$g+W08>?QAB}Cv{b}eM
z@X}ILg+uT%>-6`A25p@uhS3%;<rR|*N1kf&1P^IVMa6e|)S)1?<4{)#d_eV^^Cekg
zl8fq}b#YJ8rxZ%pb5Tv7+fJ_a2Mp|*BRbo8GN3gW)7>u>ccSq}8|H_^o&`nBT5S0y
z;2H0I^(4MO*S+(4l$gULc4KSeKvidto5Nl0P|<V_!btV;ljj-o{9cM<J#_JY-%hMg
zxQ&ZW)3*}NB~;BppsRUcYoBhnnGZMRJ8^M>%9CqQ*ikY!w_GUlo}sb9HYB=L^oFpJ
zfTQskXW!LFVnUo4(OHPDaZSf3zB|3{RGu1>ue<a*`=s_yvLbH%vcW@VCJ#aALQ|JL
zC^utq{CZyeeAeku^2h$gxq&1qRcIhf-9I(%ZJF$nJSyHp{#8N94N}m->E$(+dr?tT
zp!SGlqDU8vu{5x<AXek+rPq-Lbl+U{;7^^p@lQGIt;6y1z^{#4%9F+sflS3{B+&Ki
zxeJ9{9*Q^P*cQYVVeZlOA?UU22F2ap4a?F!j*lCdcfx4hjg~^5)`<u2$kg76XfYxs
zRmD~@S13dx>LWSvj+j$arHglg54#Lx&TvuO3LIIU>hF9Uoj&=-b*Q?uYr`#V?xz?2
zhirZrv^eA{k%{hFh%9LYVXEYWd5#PuUd1QqaqB*J!CMXEM>fEB$@#1>mtB`Bfil}t
zhhTIObqh5HRvT+4q_Do$Q<Iw$pOMZMQK<|=?I%P#z|B+&B)9IJK&qopTmxdSO3fH4
zKknW$aHwWWY|M{jqo*8_MV}M5RM;f+K_Hb0WjPm|jdWLgW%>*Jika?qV=Np-DtPkU
z(KoXyWLfPwr@UY1)hBAvR3nCBZgd|CevTG?H~HqDF}dzy%2sd2`f{^CBbTk*^K~RO
zN~O0+2EjAJlywF%SjgYz810l&G5AqzI<=Ber{912^PpSPRJl3dm8W@d<hpik9nByk
zKlDU#vYEHBs*poon6^}Uj-jr}+A-Fov6-<R=US6PG|nPnQIDuKB@<|RhVc)0WZ3p7
zNR+*I<d3Xo+K!O_n(wU0-g@0pkMmkTYPeHmh=K>KHL}7_@k3)Y!SXYkyxQy>Q4I2o
z<zo5B!6kC>r`ev7fLF$1t96h|sH<-#*YzGD-b^3$_!#wsh(Yw;)b@udLz9mm`mFYh
z1Zz24KIQJ(*_-E0(3&1InqG;U?wF<Ioa*U6`sI?EA4=z)6vf4hndRImU8^arKs_T9
z*3_5!LpI94-g<BaHDyKg)Rl(v#m(F`wOIFl_Dj3Q%A2R+t9C!Z*pN-%y7Twp_cuow
z`M>)GYd>DFo(em`#|UaaYmkA9;GTX7b?0@C@QkTVpGD#mf$<F^){<)_GYte|B<V_J
zqX%AQW#Rs?^H(vcX_CjEd-~S}Gf?=C3Qpl?9jkKo3)t@7%vvwwVq3@Gn9nF&e@&1N
zU&Er$C!LX__{~4B6~^)8Y?NI|gkCP~p(1)NtXw?!?t<2%JhI<XVukFgm7_Gz!^h6x
zA#Eh#=h)D#uoJBE$dMhd`;%S%L>dQoRNV=n{^Zi_W*ps;3?^$s`0;ER7;==~OmQ~9
zS5P=F<Clct8yi_gyp#8ZS@J^!F&w||`WQqsvXq~*8`$tI=4KUH$%eLSmTj$`MCB4U
z@}$IK#4o}vMIQD0NuFHaZ?wjdbnf>jxE5%|;xq6h4@!_h?@|aK&FYI2IT(OHXv2%1
zWEo-v!L7x^YT(xLVHlpJttcwaF@1Y;-S*q3CRa!g7xdzl|Jan>2#dI0`LKl!T1GMk
zRKe4|bQO&ET}Z^Aiym*HII>cSxIzl|F~JEUGxz;+DB=8fxX<z#)zw~yn<$bV824{{
z8QIj?)*1uU?uT+8V==gDksU}8_A%Fjhgm`9_#I_cJF#P%EGR+UO_Vr(h*Vco$b`d+
zGw}KepE%9uGHi)oXCkQAb4Gz3N>hnBI4R12q6ews$lA`Jfi}r@A@-)6TOAUMNYFYJ
zZ-Zd?lxFTyjN3mXnL!%#>Z%$0gJ4*9g;e;@zSmQ{eGGDaRRNM3s@6!;hYuVc=c+3B
z=qzNNS~n^EsJU4aOGE|mdy={C^lPKEfPL-IJAsTpQsDgZ@~s+eHZYmp9<kk{c{<R?
z@ACtxBu*G*v&O}re7*K!yU$MOzYhmliycu)_|S4`g(sa+SDrLCQut<=g{o0wBK(pV
zG1u(ptL&#?WO=J^V<AhlPZ~?uD+}1ms3?9AC-yMz24O*k-=aeNaiN|M6`8KQA4yeF
zJgCG1nJ-ytSSbt<_38e;A4E&`AS||~_E;>yb=YW_4r?lqQaYZQ`nau){W`LY#P)>i
zq^wHEuOYs#FlPZeMuT@Etb@~A6feCebq`miJE3w+gAL%bVF_s*5e*@)?xmKSo%I3?
zLE<Tr7a_+kW+<L&mYH|oQ~JO1uD+15+g^iRGl9<UKS$9DpP96;Cxxg_r`99$1{~*V
ztPe%kK0U!<xi*#2<BUM5Ym6?~rCzZf2sm&0<|wdiz!urLcYnpGIQODIwb9Io)bHo}
zC0=Sqg!NKa8aTX)|Ffq(74y`eJzD4<S{ivm@tKXnkPaokY^p^LDG>LHVdWia$}~s6
zr!^LfxSSB4Td&9iTXrzQpl5ZDo#SdmNr;23QsPHQ!x!UT9xtb!Ycz^JF8x)%cFOXK
z^EXw%dRz_VD}<c`?e*L7tL9gT&i6x#g;!bLl%8DfV&Q)dtmLTtQQ-fM0{nw(nizX)
zasM}h2GEnv;QtSpfZvnG5B`k`7_hJy|0YoXxAKF%Nr7N)%D+kVT_EZQKM2k6ublZI
z3-V^XmHkW%K>7?RU^4{)1+xFO=z!EI8IUa3U*rag=1BpHX$Xi<__kSbS{y_xa*MJv
z_`thq0Z^sPzjAk48ssDQj}!$N8Q$XC84(bU$t_Bm69Jf+C!h_}e<V3TvrG!u&q6>p
zwzpQj9sRA94<{x3{~z&ix-DwX;RAzka)4-#6ZHJqKh|SVuO|>Yrv+m30+!|sK<-|E
z=)5E->#y<_1V|T1f%<s}h|~A4qy={8H9@m4f#t*pfboJH$Rp?$2azPVjgt!y&<OI@
zB3={$QKSDNGk{oxfk2_R_<2zQR2cCO;sGR4M1aH+CnzoY*1C?N1Ev>Af!ZYqXg}`O
zI$qKOWdnclF`%_Z`WGOe{`A`l-#a?s=Q1a#@BOWmExH2;Wl`OB!B-%lq3nO{4=WO&
z#k_x|N&(qzm*6S{G*|GCegF2N2ulC+(58z2DG~yUs}i8zvRf&$CJCaexJ6Xu!`qz(
z)*v8*kAE#D0KCo*s{8^Rbg=`*E2MzeIt0|x55%n-gO&yX#$l=3W7-_~&(G8j1E(XB
hw}tl`5K!1C(72%nnjQrp<7@!WCh47rWB+@R{{wClNUHz<

diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 622ab64a..12d38de6 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index fbd7c515..4f906e0c 100755
--- a/gradlew
+++ b/gradlew
@@ -130,7 +130,7 @@ fi
 if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    
+
     JAVACMD=`cygpath --unix "$JAVACMD"`
 
     # We build the pattern for arguments to be converted via cygpath
diff --git a/gradlew.bat b/gradlew.bat
index 5093609d..107acd32 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
 
 set JAVA_EXE=java.exe
 %JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if "%ERRORLEVEL%" == "0" goto execute
 
 echo.
 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -54,7 +54,7 @@ goto fail
 set JAVA_HOME=%JAVA_HOME:"=%
 set JAVA_EXE=%JAVA_HOME%/bin/java.exe
 
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
 
 echo.
 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -64,21 +64,6 @@ echo location of your Java installation.
 
 goto fail
 
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
 :execute
 @rem Setup the command line
 
@@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
 
 
 @rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
 
 :end
 @rem End local scope for the variables with windows NT shell
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 2433e4dd..7be55542 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -5,12 +5,20 @@ pluginManagement {
         gradlePluginPortal()
         maven("https://dl.bintray.com/kotlin/kotlin-eap")
         maven("https://dl.bintray.com/kotlin/kotlinx")
-        maven("https://dl.bintray.com/mipt-npm/scientifik")
         maven("https://dl.bintray.com/mipt-npm/kscience")
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
 
     val toolsVersion = "0.6.0"
+    val kotlinVersion = "1.4.0"
+
+    plugins {
+        kotlin("jvm") version kotlinVersion
+        id("scientifik.mpp") version toolsVersion
+        id("scientifik.jvm") version toolsVersion
+        id("scientifik.js") version toolsVersion
+        id("scientifik.publish") version toolsVersion
+    }
 
     resolutionStrategy {
         eachPlugin {

From 6ad5f162a1c4a15757d37ba603c93da8982df643 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Mon, 31 Aug 2020 12:02:06 +0300
Subject: [PATCH 11/40] Refactor Name and NameToken. Breaking change

---
 .../kotlin/hep/dataforge/data/DataNode.kt     |  16 +--
 .../kotlin/hep/dataforge/meta/Meta.kt         |   2 +-
 .../kotlin/hep/dataforge/meta/MutableMeta.kt  |   6 +-
 .../meta/descriptors/ItemDescriptor.kt        |   6 +-
 .../kotlin/hep/dataforge/meta/metaMatcher.kt  |   5 +-
 .../kotlin/hep/dataforge/names/Name.kt        | 112 ++++++++++--------
 6 files changed, 78 insertions(+), 69 deletions(-)

diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt
index 246d9796..1eac4745 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt
@@ -89,8 +89,8 @@ val <T : Any> DataItem<T>?.data: Data<T>? get() = (this as? DataItem.Leaf<T>)?.d
 
 operator fun <T : Any> DataNode<T>.get(name: Name): DataItem<T>? = when (name.length) {
     0 -> error("Empty name")
-    1 -> items[name.first()]
-    else -> get(name.first()!!.asName()).node?.get(name.cutFirst())
+    1 -> items[name.firstOrNull()]
+    else -> get(name.firstOrNull()!!.asName()).node?.get(name.cutFirst())
 }
 
 operator fun <T : Any> DataNode<T>.get(name: String): DataItem<T>? = get(name.toName())
@@ -168,24 +168,24 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
     private fun buildNode(name: Name): DataTreeBuilder<T> {
         return when (name.length) {
             0 -> this
-            1 -> buildNode(name.first()!!)
-            else -> buildNode(name.first()!!).buildNode(name.cutFirst())
+            1 -> buildNode(name.firstOrNull()!!)
+            else -> buildNode(name.firstOrNull()!!).buildNode(name.cutFirst())
         }
     }
 
     operator fun set(name: Name, data: Data<T>) {
         when (name.length) {
             0 -> error("Can't add data with empty name")
-            1 -> set(name.first()!!, data)
-            2 -> buildNode(name.cutLast())[name.last()!!] = data
+            1 -> set(name.firstOrNull()!!, data)
+            2 -> buildNode(name.cutLast())[name.lastOrNull()!!] = data
         }
     }
 
     operator fun set(name: Name, node: DataTreeBuilder<out T>) {
         when (name.length) {
             0 -> error("Can't add data with empty name")
-            1 -> set(name.first()!!, node)
-            2 -> buildNode(name.cutLast())[name.last()!!] = node
+            1 -> set(name.firstOrNull()!!, node)
+            2 -> buildNode(name.cutLast())[name.lastOrNull()!!] = node
         }
     }
 
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
index fdbdab72..8bb5af94 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
@@ -115,7 +115,7 @@ public interface Meta : MetaRepr, ItemProvider {
 
     override fun getItem(name: Name): MetaItem<*>? {
         if (name.isEmpty()) return NodeItem(this)
-        return name.first()?.let { token ->
+        return name.firstOrNull()?.let { token ->
             val tail = name.cutFirst()
             when (tail.length) {
                 0 -> items[token]
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
index e782db30..64466554 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
@@ -56,12 +56,12 @@ abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(),
         when (name.length) {
             0 -> error("Can't setValue meta item for empty name")
             1 -> {
-                val token = name.first()!!
+                val token = name.firstOrNull()!!
                 @Suppress("UNCHECKED_CAST") val oldItem: MetaItem<M>? = get(name) as? MetaItem<M>
                 replaceItem(token, oldItem, wrapItem(item))
             }
             else -> {
-                val token = name.first()!!
+                val token = name.firstOrNull()!!
                 //get existing or create new node. Query is ignored for new node
                 if (items[token] == null) {
                     replaceItem(token, null, MetaItem.NodeItem(empty()))
@@ -159,7 +159,7 @@ operator fun MutableMeta<*>.set(name: String, metas: Iterable<Meta>): Unit = set
  */
 fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
     require(!name.isEmpty()) { "Name could not be empty for append operation" }
-    val newIndex = name.last()!!.index
+    val newIndex = name.lastOrNull()!!.index
     if (newIndex != null) {
         set(name, value)
     } else {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt
index a277e18d..338e1443 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt
@@ -141,7 +141,7 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
                 }
                 NodeDescriptor(config)
             }
-            else -> buildNode(name.first()?.asName()!!).buildNode(name.cutFirst())
+            else -> buildNode(name.firstOrNull()?.asName()!!).buildNode(name.cutFirst())
         }
     }
 
@@ -155,7 +155,7 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
     }
 
     fun item(name: Name, descriptor: ItemDescriptor) {
-        buildNode(name.cutLast()).newItem(name.last().toString(), descriptor)
+        buildNode(name.cutLast()).newItem(name.lastOrNull().toString(), descriptor)
     }
 
     fun item(name: String, descriptor: ItemDescriptor) {
@@ -199,7 +199,7 @@ operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
     if (name.isEmpty()) return this
     return when (this) {
         is ValueDescriptor -> null // empty name already checked
-        is NodeDescriptor -> items[name.first()!!.toString()]?.get(name.cutFirst())
+        is NodeDescriptor -> items[name.firstOrNull()!!.toString()]?.get(name.cutFirst())
     }
 }
 
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt
index 26dc009c..0ed3190b 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt
@@ -1,7 +1,6 @@
 package hep.dataforge.meta
 
-import hep.dataforge.names.Name
-import hep.dataforge.names.toName
+import hep.dataforge.names.*
 
 /**
  * Get all items matching given name. The index of the last element, if present is used as a [Regex],
@@ -14,7 +13,7 @@ fun Meta.getIndexed(name: Name): Map<String?, MetaItem<*>> {
         else -> this[name.cutLast()].node ?: return emptyMap()
     }
 
-    val (body, index) = name.last()!!
+    val (body, index) = name.lastOrNull()!!
     return if (index == null) {
         root.items.filter { it.key.body == body }.mapKeys { it.key.index }
     } else {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
index 327291d0..0791e080 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
@@ -1,5 +1,6 @@
 package hep.dataforge.names
 
+import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.Serializer
@@ -16,31 +17,8 @@ import kotlinx.serialization.encoding.Encoder
  * Each token could contain additional index in square brackets.
  */
 @Serializable
-class Name(val tokens: List<NameToken>) {
-
-    val length get() = tokens.size
-
-    /**
-     * First token of the name or null if it is empty
-     */
-    fun first(): NameToken? = tokens.firstOrNull()
-
-    /**
-     * Last token of the name or null if it is empty
-     */
-    fun last(): NameToken? = tokens.lastOrNull()
-
-    /**
-     * The reminder of the name after first element is cut. For empty name return itself.
-     */
-    fun cutFirst(): Name = Name(tokens.drop(1))
-
-    /**
-     * The reminder of the name after last element is cut. For empty name return itself.
-     */
-    fun cutLast(): Name = Name(tokens.dropLast(1))
-
-    operator fun get(i: Int): NameToken = tokens[i]
+public class Name(public val tokens: List<NameToken>) {
+    //TODO to be transformed into inline class after they are supported with serialization
 
     override fun toString(): String = tokens.joinToString(separator = NAME_SEPARATOR) { it.toString() }
 
@@ -60,11 +38,12 @@ class Name(val tokens: List<NameToken>) {
         }
     }
 
+    @OptIn(ExperimentalSerializationApi::class)
     @Serializer(Name::class)
-    companion object : KSerializer<Name> {
-        const val NAME_SEPARATOR = "."
+    public companion object : KSerializer<Name> {
+        public const val NAME_SEPARATOR: String = "."
 
-        val EMPTY = Name(emptyList())
+        public val EMPTY: Name = Name(emptyList())
 
         override val descriptor: SerialDescriptor =
             PrimitiveSerialDescriptor("hep.dataforge.names.Name", PrimitiveKind.STRING)
@@ -79,13 +58,37 @@ class Name(val tokens: List<NameToken>) {
     }
 }
 
+public operator fun Name.get(i: Int): NameToken = tokens[i]
+
+/**
+ * The reminder of the name after last element is cut. For empty name return itself.
+ */
+public fun Name.cutLast(): Name = Name(tokens.dropLast(1))
+
+/**
+ * The reminder of the name after first element is cut. For empty name return itself.
+ */
+public fun Name.cutFirst(): Name = Name(tokens.drop(1))
+
+public val Name.length: Int get() = tokens.size
+
+/**
+ * Last token of the name or null if it is empty
+ */
+public fun Name.lastOrNull(): NameToken? = tokens.lastOrNull()
+
+/**
+ * First token of the name or null if it is empty
+ */
+public fun Name.firstOrNull(): NameToken? = tokens.firstOrNull()
+
 /**
  * A single name token. Body is not allowed to be empty.
  * Following symbols are prohibited in name tokens: `{}.:\`.
  * A name token could have appendix in square brackets called *index*
  */
 @Serializable
-data class NameToken(val body: String, val index: String? = null) {
+public data class NameToken(val body: String, val index: String? = null) {
 
     init {
         if (body.isEmpty()) error("Syntax error: Name token body is empty")
@@ -103,15 +106,14 @@ data class NameToken(val body: String, val index: String? = null) {
         body.escape()
     }
 
-    fun hasIndex() = index != null
-
+    @OptIn(ExperimentalSerializationApi::class)
     @Serializer(NameToken::class)
-    companion object : KSerializer<NameToken> {
+    public companion object : KSerializer<NameToken> {
         override val descriptor: SerialDescriptor =
             PrimitiveSerialDescriptor("hep.dataforge.names.NameToken", PrimitiveKind.STRING)
 
         override fun deserialize(decoder: Decoder): NameToken {
-            return decoder.decodeString().toName().first()!!
+            return decoder.decodeString().toName().firstOrNull()!!
         }
 
         override fun serialize(encoder: Encoder, value: NameToken) {
@@ -120,13 +122,21 @@ data class NameToken(val body: String, val index: String? = null) {
     }
 }
 
-fun NameToken.withIndex(newIndex: String) = NameToken(body, newIndex)
+/**
+ * Check if index is defined for this token
+ */
+public fun NameToken.hasIndex(): Boolean = index != null
+
+/**
+ * Add or replace index part of this token
+ */
+public fun NameToken.withIndex(newIndex: String): NameToken = NameToken(body, newIndex)
 
 /**
  * Convert a [String] to name parsing it and extracting name tokens and index syntax.
  * This operation is rather heavy so it should be used with care in high performance code.
  */
-fun String.toName(): Name {
+public fun String.toName(): Name {
     if (isBlank()) return Name.EMPTY
     val tokens = sequence {
         var bodyBuilder = StringBuilder()
@@ -181,26 +191,26 @@ fun String.toName(): Name {
  * Convert the [String] to a [Name] by simply wrapping it in a single name token without parsing.
  * The input string could contain dots and braces, but they are just escaped, not parsed.
  */
-fun String.asName(): Name = if (isBlank()) Name.EMPTY else NameToken(this).asName()
+public fun String.asName(): Name = if (isBlank()) Name.EMPTY else NameToken(this).asName()
 
-operator fun NameToken.plus(other: Name): Name = Name(listOf(this) + other.tokens)
+public operator fun NameToken.plus(other: Name): Name = Name(listOf(this) + other.tokens)
 
-operator fun Name.plus(other: Name): Name = Name(this.tokens + other.tokens)
+public operator fun Name.plus(other: Name): Name = Name(this.tokens + other.tokens)
 
-operator fun Name.plus(other: String): Name = this + other.toName()
+public operator fun Name.plus(other: String): Name = this + other.toName()
 
-operator fun Name.plus(other: NameToken): Name = Name(tokens + other)
+public operator fun Name.plus(other: NameToken): Name = Name(tokens + other)
 
-fun Name.appendLeft(other: String): Name = NameToken(other) + this
+public fun Name.appendLeft(other: String): Name = NameToken(other) + this
 
-fun NameToken.asName() = Name(listOf(this))
+public fun NameToken.asName(): Name = Name(listOf(this))
 
-fun Name.isEmpty(): Boolean = this.length == 0
+public fun Name.isEmpty(): Boolean = this.length == 0
 
 /**
  * Set or replace last token index
  */
-fun Name.withIndex(index: String): Name {
+public fun Name.withIndex(index: String): Name {
     val last = NameToken(tokens.last().body, index)
     if (length == 0) error("Can't add index to empty name")
     if (length == 1) {
@@ -215,19 +225,19 @@ fun Name.withIndex(index: String): Name {
 /**
  * Fast [String]-based accessor for item map
  */
-operator fun <T> Map<NameToken, T>.get(body: String, query: String? = null): T? = get(NameToken(body, query))
+public operator fun <T> Map<NameToken, T>.get(body: String, query: String? = null): T? = get(NameToken(body, query))
 
-operator fun <T> Map<Name, T>.get(name: String) = get(name.toName())
-operator fun <T> MutableMap<Name, T>.set(name: String, value: T) = set(name.toName(), value)
+public operator fun <T> Map<Name, T>.get(name: String): T? = get(name.toName())
+public operator fun <T> MutableMap<Name, T>.set(name: String, value: T): Unit = set(name.toName(), value)
 
 /* Name comparison operations */
 
-fun Name.startsWith(token: NameToken): Boolean = first() == token
+public fun Name.startsWith(token: NameToken): Boolean = firstOrNull() == token
 
-fun Name.endsWith(token: NameToken): Boolean = last() == token
+public fun Name.endsWith(token: NameToken): Boolean = lastOrNull() == token
 
-fun Name.startsWith(name: Name): Boolean =
+public fun Name.startsWith(name: Name): Boolean =
     this.length >= name.length && tokens.subList(0, name.length) == name.tokens
 
-fun Name.endsWith(name: Name): Boolean =
+public fun Name.endsWith(name: Name): Boolean =
     this.length >= name.length && tokens.subList(length - name.length, length) == name.tokens
\ No newline at end of file

From 99fee604d8088f821c9bc0c878f042403efa33d2 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Mon, 31 Aug 2020 12:39:44 +0300
Subject: [PATCH 12/40] HTML renderer refactoring

---
 .../hep/dataforge/output/html/HtmlRenderer.kt | 23 +++++++++++--------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt b/dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt
index c0aeaaab..25cf2116 100644
--- a/dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt
+++ b/dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt
@@ -1,6 +1,7 @@
 package hep.dataforge.output.html
 
 import hep.dataforge.context.Context
+import hep.dataforge.meta.DFExperimental
 import hep.dataforge.meta.Meta
 import hep.dataforge.output.Output
 import hep.dataforge.output.Renderer
@@ -10,12 +11,14 @@ import hep.dataforge.provider.Type
 import hep.dataforge.provider.top
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
+import kotlinx.html.FlowContent
 import kotlinx.html.TagConsumer
 import kotlinx.html.p
 import kotlin.reflect.KClass
 
 
-class HtmlRenderer<T : Any>(override val context: Context, private val consumer: TagConsumer<*>) : Renderer<T> {
+@DFExperimental
+public class HtmlRenderer<T : Any>(override val context: Context, private val consumer: TagConsumer<*>) : Renderer<T> {
     private val cache = HashMap<KClass<*>, HtmlBuilder<*>>()
 
     /**
@@ -42,7 +45,7 @@ class HtmlRenderer<T : Any>(override val context: Context, private val consumer:
         }
         context.launch(Dispatchers.Output) {
             @Suppress("UNCHECKED_CAST")
-            (builder as HtmlBuilder<T>).run { consumer.render(obj) }
+            (builder as HtmlBuilder<T>).run { render(obj) }
         }
     }
 }
@@ -51,29 +54,29 @@ class HtmlRenderer<T : Any>(override val context: Context, private val consumer:
  * A text or binary renderer based on [Renderer]
  */
 @Type(HTML_CONVERTER_TYPE)
-interface HtmlBuilder<T : Any> {
+public interface HtmlBuilder<T : Any> {
     /**
      * The priority of this renderer compared to other renderers
      */
-    val priority: Int
+    public val priority: Int
 
     /**
      * The type of the content served by this renderer
      */
-    val type: KClass<T>
+    public val type: KClass<T>
 
-    suspend fun TagConsumer<*>.render(obj: T)
+    public suspend fun FlowContent.render(obj: T)
 
-    companion object {
-        const val HTML_CONVERTER_TYPE = "dataforge.htmlBuilder"
+    public companion object {
+        public const val HTML_CONVERTER_TYPE: String = "dataforge.htmlBuilder"
     }
 }
 
-object DefaultHtmlBuilder : HtmlBuilder<Any> {
+public object DefaultHtmlBuilder : HtmlBuilder<Any> {
     override val priority: Int = Int.MAX_VALUE
     override val type: KClass<Any> = Any::class
 
-    override suspend fun TagConsumer<*>.render(obj: Any) {
+    override suspend fun FlowContent.render(obj: Any) {
         p { +obj.toString() }
     }
 }
\ No newline at end of file

From b7d01bc40f00990aa7d4ae3cdcec1b36e42c8b6c Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Wed, 2 Sep 2020 12:11:44 +0300
Subject: [PATCH 13/40] Using dev plugin

---
 settings.gradle.kts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/settings.gradle.kts b/settings.gradle.kts
index 7be55542..5f89216d 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -9,7 +9,7 @@ pluginManagement {
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
 
-    val toolsVersion = "0.6.0"
+    val toolsVersion = "0.6.0-dev-1"
     val kotlinVersion = "1.4.0"
 
     plugins {

From a767f279a3df565181a7f5f4e0370317cb6ebabd Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sat, 5 Sep 2020 16:19:03 +0300
Subject: [PATCH 14/40] Fixed 1.4 build

---
 build.gradle.kts                              |  7 +++----
 dataforge-context/build.gradle.kts            |  4 +++-
 dataforge-data/build.gradle.kts               |  4 +++-
 .../kotlin/hep/dataforge/data/dataJVM.kt      |  2 +-
 dataforge-io/build.gradle.kts                 |  4 +++-
 .../dataforge-io-yaml/build.gradle.kts        |  3 +--
 .../hep/dataforge/io/MetaSerializerTest.kt    |  2 ++
 dataforge-meta/build.gradle.kts               |  4 +++-
 dataforge-output/build.gradle.kts             |  4 +++-
 .../dataforge-output-html/build.gradle.kts    |  2 +-
 dataforge-scripting/build.gradle.kts          |  2 +-
 dataforge-tables/build.gradle.kts             |  2 +-
 dataforge-workspace/build.gradle.kts          |  2 +-
 settings.gradle.kts                           | 21 +++++++------------
 14 files changed, 33 insertions(+), 30 deletions(-)

diff --git a/build.gradle.kts b/build.gradle.kts
index 09240c13..81c6578b 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,10 +1,9 @@
 plugins {
-    id("kscience.publish") apply false
-    id("org.jetbrains.dokka") version "1.4.0-rc"
+    id("ru.mipt.npm.publish") apply false
     id("org.jetbrains.changelog") version "0.4.0"
 }
 
-val dataforgeVersion by extra("0.1.9-dev-2")
+val dataforgeVersion by extra("0.1.9-dev-5")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
@@ -20,6 +19,6 @@ allprojects {
 }
 
 subprojects {
-    apply(plugin = "kscience.publish")
+    apply(plugin = "ru.mipt.npm.publish")
     apply(plugin = "org.jetbrains.dokka")
 }
\ No newline at end of file
diff --git a/dataforge-context/build.gradle.kts b/dataforge-context/build.gradle.kts
index a41e4443..74964376 100644
--- a/dataforge-context/build.gradle.kts
+++ b/dataforge-context/build.gradle.kts
@@ -1,5 +1,7 @@
 plugins {
-    id("kscience.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.node")
+//    id("ru.mipt.npm.native")
 }
 
 description = "Context and provider definitions"
diff --git a/dataforge-data/build.gradle.kts b/dataforge-data/build.gradle.kts
index 6afb4230..587f7492 100644
--- a/dataforge-data/build.gradle.kts
+++ b/dataforge-data/build.gradle.kts
@@ -1,5 +1,7 @@
 plugins {
-    id("kscience.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.node")
+//    id("ru.mipt.npm.native")
 }
 
 kscience{
diff --git a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
index e385acc3..34148b4d 100644
--- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
+++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
@@ -14,7 +14,7 @@ public fun <T : Any> Data<T>.get(): T = runBlocking { await() }
  * Check that node is compatible with given type meaning that each element could be cast to the type
  */
 internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
-    type.isSuperclassOf(type)
+    this.type.isSubclassOf(type)
 
 internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
     this.type.isSubclassOf(type)
diff --git a/dataforge-io/build.gradle.kts b/dataforge-io/build.gradle.kts
index d7d0d8fb..6525a243 100644
--- a/dataforge-io/build.gradle.kts
+++ b/dataforge-io/build.gradle.kts
@@ -1,5 +1,7 @@
 plugins {
-    id("kscience.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.node")
+//    id("ru.mipt.npm.native")
 }
 
 description = "IO module"
diff --git a/dataforge-io/dataforge-io-yaml/build.gradle.kts b/dataforge-io/dataforge-io-yaml/build.gradle.kts
index be1cace6..720e1fba 100644
--- a/dataforge-io/dataforge-io-yaml/build.gradle.kts
+++ b/dataforge-io/dataforge-io-yaml/build.gradle.kts
@@ -1,6 +1,5 @@
-
 plugins {
-    id("kscience.jvm")
+    id("ru.mipt.npm.jvm")
 }
 
 description = "YAML meta IO"
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
index 1f3b235d..75496d7b 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
@@ -3,6 +3,7 @@ package hep.dataforge.io
 import hep.dataforge.meta.*
 import hep.dataforge.names.Name
 import hep.dataforge.names.toName
+import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.cbor.Cbor
 import kotlin.test.Test
 import kotlin.test.assertEquals
@@ -24,6 +25,7 @@ class MetaSerializerTest {
         assertEquals(meta, restored)
     }
 
+    @OptIn(ExperimentalSerializationApi::class)
     @Test
     fun testCborSerialization() {
         val bytes = Cbor.encodeToByteArray(MetaSerializer, meta)
diff --git a/dataforge-meta/build.gradle.kts b/dataforge-meta/build.gradle.kts
index 78a9a895..36357552 100644
--- a/dataforge-meta/build.gradle.kts
+++ b/dataforge-meta/build.gradle.kts
@@ -1,5 +1,7 @@
 plugins {
-    id("kscience.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.node")
+    id("ru.mipt.npm.native")
 }
 
 kscience {
diff --git a/dataforge-output/build.gradle.kts b/dataforge-output/build.gradle.kts
index d84333ba..1de9ca2e 100644
--- a/dataforge-output/build.gradle.kts
+++ b/dataforge-output/build.gradle.kts
@@ -1,5 +1,7 @@
 plugins {
-    id("kscience.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.node")
+//    id("ru.mipt.npm.native")
 }
 
 kotlin {
diff --git a/dataforge-output/dataforge-output-html/build.gradle.kts b/dataforge-output/dataforge-output-html/build.gradle.kts
index fe2de0b9..4b8bdbda 100644
--- a/dataforge-output/dataforge-output-html/build.gradle.kts
+++ b/dataforge-output/dataforge-output-html/build.gradle.kts
@@ -1,5 +1,5 @@
 plugins {
-    id("kscience.mpp")
+    id("ru.mipt.npm.mpp")
 }
 
 val htmlVersion by rootProject.extra("0.7.2")
diff --git a/dataforge-scripting/build.gradle.kts b/dataforge-scripting/build.gradle.kts
index 9eb40708..cb16b66e 100644
--- a/dataforge-scripting/build.gradle.kts
+++ b/dataforge-scripting/build.gradle.kts
@@ -1,5 +1,5 @@
 plugins {
-    id("kscience.mpp")
+    id("ru.mipt.npm.mpp")
 }
 
 kotlin {
diff --git a/dataforge-tables/build.gradle.kts b/dataforge-tables/build.gradle.kts
index d84333ba..b181416b 100644
--- a/dataforge-tables/build.gradle.kts
+++ b/dataforge-tables/build.gradle.kts
@@ -1,5 +1,5 @@
 plugins {
-    id("kscience.mpp")
+    id("ru.mipt.npm.mpp")
 }
 
 kotlin {
diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts
index 0c1972cd..8abe87cd 100644
--- a/dataforge-workspace/build.gradle.kts
+++ b/dataforge-workspace/build.gradle.kts
@@ -1,5 +1,5 @@
 plugins {
-    id("kscience.mpp")
+    id("ru.mipt.npm.mpp")
 }
 
 kotlin {
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 5f89216d..b6f80363 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -3,29 +3,22 @@ pluginManagement {
         mavenLocal()
         jcenter()
         gradlePluginPortal()
-        maven("https://dl.bintray.com/kotlin/kotlin-eap")
-        maven("https://dl.bintray.com/kotlin/kotlinx")
+        maven("https://dl.bintray.com/mipt-npm/dataforge")
         maven("https://dl.bintray.com/mipt-npm/kscience")
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
 
-    val toolsVersion = "0.6.0-dev-1"
+    val toolsVersion = "0.6.0-dev-3"
     val kotlinVersion = "1.4.0"
 
     plugins {
+        id("ru.mipt.npm.mpp") version toolsVersion
+        id("ru.mipt.npm.jvm") version toolsVersion
+        id("ru.mipt.npm.js") version toolsVersion
+        id("ru.mipt.npm.publish") version toolsVersion
         kotlin("jvm") version kotlinVersion
-        id("scientifik.mpp") version toolsVersion
-        id("scientifik.jvm") version toolsVersion
-        id("scientifik.js") version toolsVersion
-        id("scientifik.publish") version toolsVersion
-    }
+        kotlin("js") version kotlinVersion
 
-    resolutionStrategy {
-        eachPlugin {
-            when (requested.id.id) {
-                "kscience.mpp", "kscience.jvm", "kscience.js", "kscience.publish" -> useModule("ru.mipt.npm:gradle-tools:${toolsVersion}")
-            }
-        }
     }
 }
 

From eeb4643d936f895aa30a57e999a093640f16d2ab Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Mon, 7 Sep 2020 13:44:02 +0300
Subject: [PATCH 15/40] IO refactoring

---
 build.gradle.kts                              |  4 +-
 dataforge-context/build.gradle.kts            |  2 +-
 .../hep/dataforge/context/AbstractPlugin.kt   |  4 +-
 .../kotlin/hep/dataforge/context/Context.kt   | 77 ++++---------------
 .../hep/dataforge/context/ContextBuilder.kt   | 19 +++--
 .../kotlin/hep/dataforge/context/Global.kt    | 43 +++++++++++
 .../hep/dataforge/context/PluginManager.kt    | 11 +++
 .../hep/dataforge/context/PluginRepository.kt | 48 ------------
 .../hep/dataforge/context/ContextTest.kt      |  2 +-
 .../hep/dataforge/context/PluginRepository.kt | 16 ----
 .../hep/dataforge/context/PluginRepository.kt | 17 ----
 .../kotlin/hep/dataforge/provider/Types.kt    |  4 +-
 .../io/yaml/FrontMatterEnvelopeFormat.kt      | 37 ++++-----
 .../hep/dataforge/io/yaml/YamlMetaFormat.kt   | 25 +++---
 .../hep/dataforge/io/BinaryMetaFormat.kt      | 30 +++++---
 .../kotlin/hep/dataforge/io/Envelope.kt       | 44 ++++++-----
 .../kotlin/hep/dataforge/io/EnvelopeFormat.kt | 27 +++----
 .../kotlin/hep/dataforge/io/EnvelopeParts.kt  | 16 ++--
 .../kotlin/hep/dataforge/io/IOFormat.kt       | 67 ++++++++--------
 .../kotlin/hep/dataforge/io/IOPlugin.kt       | 32 ++++----
 .../kotlin/hep/dataforge/io/JsonMetaFormat.kt | 28 +++----
 .../kotlin/hep/dataforge/io/MetaFormat.kt     | 40 +++++-----
 .../hep/dataforge/io/TaggedEnvelopeFormat.kt  | 42 +++++-----
 .../hep/dataforge/io/TaglessEnvelopeFormat.kt | 77 ++++++++++---------
 .../kotlin/hep/dataforge/io/MetaFormatTest.kt |  4 +-
 .../kotlin/hep/dataforge/io/ioTestUtils.kt    |  4 +-
 .../jvmMain/kotlin/hep/dataforge/io/fileIO.kt | 36 ++++-----
 .../hep/dataforge/io/tcp/EnvelopeClient.kt    |  4 +-
 .../hep/dataforge/io/tcp/EnvelopeServer.kt    |  6 +-
 .../dataforge/workspace/SimpleWorkspace.kt    |  4 +-
 .../dataforge/workspace/WorkspaceBuilder.kt   |  2 +-
 .../hep/dataforge/workspace/fileData.kt       |  2 +-
 .../hep/dataforge/workspace/FileDataTest.kt   |  8 +-
 settings.gradle.kts                           |  2 +-
 34 files changed, 371 insertions(+), 413 deletions(-)
 create mode 100644 dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
 delete mode 100644 dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginRepository.kt
 delete mode 100644 dataforge-context/src/jsMain/kotlin/hep/dataforge/context/PluginRepository.kt
 delete mode 100644 dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/PluginRepository.kt

diff --git a/build.gradle.kts b/build.gradle.kts
index 81c6578b..4364d684 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -3,7 +3,9 @@ plugins {
     id("org.jetbrains.changelog") version "0.4.0"
 }
 
-val dataforgeVersion by extra("0.1.9-dev-5")
+apply(plugin = "org.jetbrains.dokka")
+
+val dataforgeVersion by extra("0.2.0-dev-1")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/dataforge-context/build.gradle.kts b/dataforge-context/build.gradle.kts
index 74964376..3ef9f80f 100644
--- a/dataforge-context/build.gradle.kts
+++ b/dataforge-context/build.gradle.kts
@@ -1,7 +1,7 @@
 plugins {
     id("ru.mipt.npm.mpp")
     id("ru.mipt.npm.node")
-//    id("ru.mipt.npm.native")
+    id("ru.mipt.npm.native")
 }
 
 description = "Context and provider definitions"
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt
index 42adce2c..f64c1042 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt
@@ -6,7 +6,7 @@ import kotlin.properties.ReadOnlyProperty
 import kotlin.reflect.KClass
 import kotlin.reflect.KProperty
 
-abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plugin {
+public abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plugin {
     private var _context: Context? = null
     private val dependencies = ArrayList<PluginFactory<*>>()
 
@@ -32,7 +32,7 @@ abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plugin {
     }
 }
 
-fun <T : Named> Collection<T>.toMap(): Map<Name, T> = associate { it.name to it }
+public fun <T : Named> Collection<T>.toMap(): Map<Name, T> = associate { it.name to it }
 
 private class PluginDependencyDelegate<P : Plugin>(val type: KClass<out P>) : ReadOnlyProperty<AbstractPlugin, P> {
     override fun getValue(thisRef: AbstractPlugin, property: KProperty<*>): P {
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
index 8bcdff57..f9f07aef 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
@@ -2,13 +2,11 @@ package hep.dataforge.context
 
 import hep.dataforge.meta.*
 import hep.dataforge.names.Name
-import hep.dataforge.names.asName
 import hep.dataforge.names.plus
 import hep.dataforge.provider.Provider
 import hep.dataforge.provider.top
 import hep.dataforge.values.Value
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.SupervisorJob
 import mu.KLogger
@@ -28,9 +26,9 @@ import kotlin.jvm.JvmName
  * Since plugins could contain mutable state, context has two states: active and inactive. No changes are allowed to active context.
  * @author Alexander Nozik
  */
-open class Context(
+public open class Context(
     final override val name: Name,
-    val parent: Context? = Global
+    public val parent: Context? = Global,
 ) : Named, MetaRepr, Provider, CoroutineScope {
 
     private val config = Config()
@@ -38,7 +36,7 @@ open class Context(
     /**
      * Context properties. Working as substitute for environment variables
      */
-    val properties: Meta = if (parent == null) {
+    private val properties: Meta = if (parent == null) {
         config
     } else {
         Laminate(config, parent.properties)
@@ -47,19 +45,19 @@ open class Context(
     /**
      * Context logger
      */
-    val logger: KLogger = KotlinLogging.logger(name.toString())
+    public val logger: KLogger = KotlinLogging.logger(name.toString())
 
     /**
      * A [PluginManager] for current context
      */
-    val plugins: PluginManager by lazy { PluginManager(this) }
+    public val plugins: PluginManager by lazy { PluginManager(this) }
 
     private val activators = HashSet<Any>()
 
     /**
      * Defines if context is used in any kind of active computations. Active context properties and plugins could not be changed
      */
-    val isActive: Boolean = activators.isNotEmpty()
+    public val isActive: Boolean = activators.isNotEmpty()
 
     override val defaultTarget: String get() = Plugin.PLUGIN_TARGET
 
@@ -74,21 +72,21 @@ open class Context(
     /**
      * Mark context as active and used by [activator]
      */
-    fun activate(activator: Any) {
+    public fun activate(activator: Any) {
         activators.add(activator)
     }
 
     /**
      * Mark context unused by [activator]
      */
-    fun deactivate(activator: Any) {
+    public fun deactivate(activator: Any) {
         activators.remove(activator)
     }
 
     /**
      * Change the properties of the context. If active, throw an exception
      */
-    fun configure(action: Config.() -> Unit) {
+    public fun configure(action: Config.() -> Unit) {
         if (isActive) error("Can't configure active context")
         config.action()
     }
@@ -102,7 +100,7 @@ open class Context(
     /**
      * Detach all plugins and terminate context
      */
-    open fun close() {
+    public open fun close() {
         if (isActive) error("Can't close active context")
         //detach all plugins
         plugins.forEach { it.detach() }
@@ -115,71 +113,30 @@ open class Context(
     }
 }
 
-fun Context.content(target: String): Map<Name, Any> = content<Any>(target)
-
 /**
  * A map of all objects provided by plugins with given target and type
  */
 @JvmName("typedContent")
-inline fun <reified T : Any> Context.content(target: String): Map<Name, T> =
-    plugins.flatMap { plugin ->
-        plugin.top<T>(target).entries.map { (plugin.name + it.key) to it.value }
-    }.associate { it }
+public inline fun <reified T : Any> Context.resolve(target: String): Map<Name, T> = plugins.flatMap { plugin ->
+    plugin.top<T>(target).entries.map { (plugin.name + it.key) to it.value }
+}.associate { it }
 
 
-/**
- * A global root context. Closing [Global] terminates the framework.
- */
-object Global : Context("GLOBAL".asName(), null) {
-
-    override val coroutineContext: CoroutineContext = GlobalScope.coroutineContext + SupervisorJob()
-
-    /**
-     * Closing all contexts
-     *
-     * @throws Exception
-     */
-    override fun close() {
-        logger.info { "Shutting down GLOBAL" }
-        for (ctx in contextRegistry.values) {
-            ctx.close()
-        }
-        super.close()
-    }
-
-    private val contextRegistry = HashMap<String, Context>()
-
-    /**
-     * Get previously built context
-     *
-     * @param name
-     * @return
-     */
-    fun getContext(name: String): Context? {
-        return contextRegistry[name]
-    }
-
-    fun context(name: String, parent: Context = this, block: ContextBuilder.() -> Unit = {}): Context =
-        ContextBuilder(name, parent).apply(block).build()
-
-}
-
+public fun Context.resolve(target: String): Map<Name, Any> = resolve<Any>(target)
 
 /**
  * The interface for something that encapsulated in context
  *
- * @author Alexander Nozik
- * @version $Id: $Id
  */
-interface ContextAware {
+public interface ContextAware {
     /**
      * Get context for this object
      *
      * @return
      */
-    val context: Context
+    public val context: Context
 
-    val logger: KLogger
+    public val logger: KLogger
         get() = if (this is Named) {
             KotlinLogging.logger((context.name + this.name).toString())
         } else {
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
index 70187191..ecb6726e 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
@@ -9,31 +9,34 @@ import hep.dataforge.names.toName
  * A convenience builder for context
  */
 @DFBuilder
-class ContextBuilder(var name: String = "@anonymous", val parent: Context = Global) {
+public class ContextBuilder(private val parent: Context = Global, public var name: String = "@anonymous") {
     private val plugins = ArrayList<Plugin>()
     private var meta = MetaBuilder()
 
-    fun properties(action: MetaBuilder.() -> Unit) {
+    public fun properties(action: MetaBuilder.() -> Unit) {
         meta.action()
     }
 
-    fun plugin(plugin: Plugin) {
+    public fun plugin(plugin: Plugin) {
         plugins.add(plugin)
     }
 
-    fun plugin(tag: PluginTag, action: MetaBuilder.() -> Unit = {}) {
-        plugins.add(PluginRepository.fetch(tag, Meta(action)))
+    public fun plugin(tag: PluginTag, action: MetaBuilder.() -> Unit = {}) {
+        val factory = parent.resolve<PluginFactory<*>>(PluginFactory.TYPE).values
+            .find { it.tag.matches(tag) } ?: error("Can't resolve plugin factory for $tag")
+        val plugin = factory.invoke(Meta(action), parent)
+        plugins.add(plugin)
     }
 
-    fun plugin(builder: PluginFactory<*>, action: MetaBuilder.() -> Unit = {}) {
+    public fun plugin(builder: PluginFactory<*>, action: MetaBuilder.() -> Unit = {}) {
         plugins.add(builder.invoke(Meta(action)))
     }
 
-    fun plugin(name: String, group: String = "", version: String = "", action: MetaBuilder.() -> Unit = {}) {
+    public fun plugin(name: String, group: String = "", version: String = "", action: MetaBuilder.() -> Unit = {}) {
         plugin(PluginTag(name, group, version), action)
     }
 
-    fun build(): Context {
+    public fun build(): Context {
         return Context(name.toName(), parent).apply {
             this@ContextBuilder.plugins.forEach {
                 plugins.load(it)
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
new file mode 100644
index 00000000..d7a52c46
--- /dev/null
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
@@ -0,0 +1,43 @@
+package hep.dataforge.context
+
+import hep.dataforge.names.asName
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.SupervisorJob
+import kotlin.coroutines.CoroutineContext
+
+/**
+ * A global root context. Closing [Global] terminates the framework.
+ */
+public object Global : Context("GLOBAL".asName(), null) {
+
+    override val coroutineContext: CoroutineContext = GlobalScope.coroutineContext + SupervisorJob()
+
+    /**
+     * Closing all contexts
+     *
+     * @throws Exception
+     */
+    override fun close() {
+        logger.info { "Shutting down GLOBAL" }
+        for (ctx in contextRegistry.values) {
+            ctx.close()
+        }
+        super.close()
+    }
+
+    private val contextRegistry = HashMap<String, Context>()
+
+    /**
+     * Get previously built context
+     *
+     * @param name
+     * @return
+     */
+    public fun getContext(name: String): Context? {
+        return contextRegistry[name]
+    }
+
+    public fun context(name: String, parent: Context = this, block: ContextBuilder.() -> Unit = {}): Context =
+        ContextBuilder(parent, name).apply(block).build()
+
+}
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
index e6e8464e..4f4a062a 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
@@ -4,6 +4,17 @@ import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaBuilder
 import kotlin.reflect.KClass
 
+
+interface PluginFactory<T : Plugin> : Factory<T> {
+    val tag: PluginTag
+    val type: KClass<out T>
+
+    companion object{
+        const val TYPE = "pluginFactory"
+    }
+}
+
+
 /**
  * The manager for plugin system. Should monitor plugin dependencies and locks.
  *
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginRepository.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginRepository.kt
deleted file mode 100644
index 248b239c..00000000
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginRepository.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package hep.dataforge.context
-
-import hep.dataforge.meta.Meta
-import kotlin.reflect.KClass
-
-interface PluginFactory<T : Plugin> : Factory<T> {
-    val tag: PluginTag
-    val type: KClass<out T>
-}
-
-expect object PluginRepository {
-
-    fun register(factory: PluginFactory<*>)
-
-    /**
-     * List plugins available in the repository
-     */
-    fun list(): Sequence<PluginFactory<*>>
-
-}
-
-/**
- * Fetch specific plugin and instantiate it with given meta
- */
-fun PluginRepository.fetch(tag: PluginTag, meta: Meta = Meta.EMPTY): Plugin =
-    list().find { it.tag.matches(tag) }?.invoke(meta = meta)
-        ?: error("Plugin with tag $tag not found in the repository")
-
-fun <T : Plugin> PluginRepository.register(
-    tag: PluginTag,
-    type: KClass<out T>,
-    constructor: (Context, Meta) -> T
-): PluginFactory<T> {
-    val factory = object : PluginFactory<T> {
-        override val tag: PluginTag = tag
-        override val type: KClass<out T> = type
-
-        override fun invoke(meta: Meta, context: Context): T = constructor(context, meta)
-
-    }
-    register(factory)
-    return factory
-}
-
-inline fun <reified T : Plugin> PluginRepository.register(tag: PluginTag, noinline constructor: (Context, Meta) -> T) =
-    register(tag, T::class, constructor)
-
-fun PluginRepository.register(plugin: Plugin) = register(plugin.tag, plugin::class) { _, _ -> plugin }
\ No newline at end of file
diff --git a/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt b/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
index 584e500c..ba7e17de 100644
--- a/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
+++ b/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
@@ -22,7 +22,7 @@ class ContextTest {
     @Test
     fun testPluginManager() {
         Global.plugins.load(DummyPlugin())
-        val members = Global.content<Name>("test")
+        val members = Global.resolve<Name>("test")
         assertEquals(3, members.count())
         members.forEach {
             assertEquals(it.key, it.value.appendLeft("test"))
diff --git a/dataforge-context/src/jsMain/kotlin/hep/dataforge/context/PluginRepository.kt b/dataforge-context/src/jsMain/kotlin/hep/dataforge/context/PluginRepository.kt
deleted file mode 100644
index 78a2952e..00000000
--- a/dataforge-context/src/jsMain/kotlin/hep/dataforge/context/PluginRepository.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package hep.dataforge.context
-
-
-actual object PluginRepository {
-
-    private val factories: MutableSet<PluginFactory<*>> = HashSet()
-
-    actual fun register(factory: PluginFactory<*>) {
-        factories.add(factory)
-    }
-
-    /**
-     * List plugins available in the repository
-     */
-    actual fun list(): Sequence<PluginFactory<*>> = factories.asSequence()
-}
\ No newline at end of file
diff --git a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/PluginRepository.kt b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/PluginRepository.kt
deleted file mode 100644
index 83455fd6..00000000
--- a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/PluginRepository.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package hep.dataforge.context
-
-actual object PluginRepository {
-
-    private val factories: MutableSet<PluginFactory<*>> = HashSet()
-
-    actual fun register(factory: PluginFactory<*>) {
-        factories.add(factory)
-    }
-
-    /**
-     * List plugins available in the repository
-     */
-    actual fun list(): Sequence<PluginFactory<*>> =
-        factories.asSequence() + Global.services()
-
-}
\ No newline at end of file
diff --git a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
index a7c27662..232e2655 100644
--- a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
+++ b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
@@ -1,7 +1,7 @@
 package hep.dataforge.provider
 
 import hep.dataforge.context.Context
-import hep.dataforge.context.content
+import hep.dataforge.context.resolve
 import hep.dataforge.names.Name
 import kotlin.reflect.KClass
 import kotlin.reflect.full.findAnnotation
@@ -40,5 +40,5 @@ inline fun <reified T : Any> Provider.top(): Map<Name, T> {
 /**
  * A sequences of all objects provided by plugins with given target and type
  */
-inline fun <reified T : Any> Context.content(): Map<Name, T> = content<T>(Types[T::class])
+inline fun <reified T : Any> Context.content(): Map<Name, T> = resolve<T>(Types[T::class])
 
diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
index bc334de5..76d1b152 100644
--- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
+++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
@@ -13,14 +13,14 @@ import kotlinx.io.text.writeUtf8String
 @DFExperimental
 class FrontMatterEnvelopeFormat(
     val io: IOPlugin,
-    val meta: Meta = Meta.EMPTY
+    val meta: Meta = Meta.EMPTY,
 ) : EnvelopeFormat {
 
-    override fun Input.readPartial(): PartialEnvelope {
+    override fun readPartial(input: Input): PartialEnvelope {
         var line = ""
         var offset = 0u
         do {
-            line = readUtf8Line() //?: error("Input does not contain front matter separator")
+            line = input.readUtf8Line() //?: error("Input does not contain front matter separator")
             offset += line.toByteArray().size.toUInt()
         } while (!line.startsWith(SEPARATOR))
 
@@ -31,22 +31,21 @@ class FrontMatterEnvelopeFormat(
         //TODO replace by preview
         val meta = Binary {
             do {
-                line = readUtf8Line()
+                line = input.readUtf8Line()
                 writeUtf8String(line + "\r\n")
                 offset += line.toByteArray().size.toUInt()
             } while (!line.startsWith(SEPARATOR))
         }.read {
-            readMetaFormat.run {
-                readMeta()
-            }
+            readMetaFormat.readMeta(input)
+
         }
         return PartialEnvelope(meta, offset, null)
     }
 
-    override fun Input.readObject(): Envelope {
+    override fun readObject(input: Input): Envelope {
         var line = ""
         do {
-            line = readUtf8Line() //?: error("Input does not contain front matter separator")
+            line = input.readUtf8Line() //?: error("Input does not contain front matter separator")
         } while (!line.startsWith(SEPARATOR))
 
         val readMetaFormat =
@@ -55,14 +54,12 @@ class FrontMatterEnvelopeFormat(
 
         val meta = Binary {
             do {
-                writeUtf8String(readUtf8Line() + "\r\n")
+                writeUtf8String(input.readUtf8Line() + "\r\n")
             } while (!line.startsWith(SEPARATOR))
         }.read {
-            readMetaFormat.run {
-                readMeta()
-            }
+            readMetaFormat.readMeta(input)
         }
-        val bytes = readByteArray()
+        val bytes = input.readByteArray()
         val data = bytes.asBinary()
         return SimpleEnvelope(meta, data)
     }
@@ -70,7 +67,7 @@ class FrontMatterEnvelopeFormat(
     override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
         val metaFormat = metaFormatFactory(formatMeta, io.context)
         writeRawString("$SEPARATOR\r\n")
-        metaFormat.run { writeObject(envelope.meta) }
+        metaFormat.run { writeObject(this@writeEnvelope, envelope.meta) }
         writeRawString("$SEPARATOR\r\n")
         //Printing data
         envelope.data?.let { data ->
@@ -105,14 +102,14 @@ class FrontMatterEnvelopeFormat(
 
         private val default by lazy { invoke() }
 
-        override fun Input.readPartial(): PartialEnvelope =
-            default.run { readPartial() }
+        override fun readPartial(input: Input): PartialEnvelope =
+            default.readPartial(input)
 
-        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) =
+        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
             default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
 
-        override fun Input.readObject(): Envelope =
-            default.run { readObject() }
+        override fun readObject(input: Input): Envelope =
+            default.readObject(input)
 
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt
index 5806abf8..18e8af06 100644
--- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt
+++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt
@@ -16,17 +16,20 @@ import kotlinx.io.asInputStream
 import kotlinx.io.text.writeUtf8String
 import org.yaml.snakeyaml.Yaml
 
+/**
+ * Represent meta as Yaml
+ */
 @DFExperimental
-class YamlMetaFormat(val meta: Meta) : MetaFormat {
+public class YamlMetaFormat(private val meta: Meta) : MetaFormat {
     private val yaml = Yaml()
 
-    override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) {
+    override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) {
         val string = yaml.dump(meta.toMap(descriptor))
-        writeUtf8String(string)
+        output.writeUtf8String(string)
     }
 
-    override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
-        val map: Map<String, Any?> = yaml.load(asInputStream())
+    override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
+        val map: Map<String, Any?> = yaml.load(input.asInputStream())
         return map.toMeta(descriptor)
     }
 
@@ -35,19 +38,19 @@ class YamlMetaFormat(val meta: Meta) : MetaFormat {
         META_KEY put meta
     }
 
-    companion object : MetaFormatFactory {
+    public companion object : MetaFormatFactory {
         override fun invoke(meta: Meta, context: Context): MetaFormat = YamlMetaFormat(meta)
 
-        override val shortName = "yaml"
+        override val shortName: String = "yaml"
 
         override val key: Short = 0x594d //YM
 
         private val default = YamlMetaFormat()
 
-        override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) =
-            default.run { writeMeta(meta, descriptor) }
+        override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?): Unit =
+            default.writeMeta(output, meta, descriptor)
 
-        override fun Input.readMeta(descriptor: NodeDescriptor?): Meta =
-            default.run { readMeta(descriptor) }
+        override fun readMeta(input: kotlinx.io.Input, descriptor: NodeDescriptor?): Meta =
+            default.readMeta(input, descriptor)
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt
index e753b56c..547d567c 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt
@@ -11,14 +11,18 @@ import kotlinx.io.*
 import kotlinx.io.text.readUtf8String
 import kotlinx.io.text.writeUtf8String
 
-object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
+/**
+ * A DataForge-specific simplified binary format for meta
+ * TODO add description
+ */
+public object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
     override val shortName: String = "bin"
     override val key: Short = 0x4249//BI
 
     override fun invoke(meta: Meta, context: Context): MetaFormat = this
 
-    override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
-        return (readMetaItem() as MetaItem.NodeItem).node
+    override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
+        return (input.readMetaItem() as MetaItem.NodeItem).node
     }
 
     private fun Output.writeChar(char: Char) = writeByte(char.toByte())
@@ -28,7 +32,7 @@ object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
         writeUtf8String(str)
     }
 
-    fun Output.writeValue(value: Value) {
+    public fun Output.writeValue(value: Value) {
         if (value.isList()) {
             writeChar('L')
             writeInt(value.list.size)
@@ -75,17 +79,21 @@ object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
         }
     }
 
-    override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) {
-        writeChar('M')
-        writeInt(meta.items.size)
+    override fun writeMeta(
+        output: kotlinx.io.Output,
+        meta: hep.dataforge.meta.Meta,
+        descriptor: hep.dataforge.meta.descriptors.NodeDescriptor?
+    ) {
+        output.writeChar('M')
+        output.writeInt(meta.items.size)
         meta.items.forEach { (key, item) ->
-            writeString(key.toString())
+            output.writeString(key.toString())
             when (item) {
                 is MetaItem.ValueItem -> {
-                    writeValue(item.value)
+                    output.writeValue(item.value)
                 }
                 is MetaItem.NodeItem -> {
-                    writeObject(item.node)
+                    writeObject(output, item.node)
                 }
             }
         }
@@ -97,7 +105,7 @@ object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
     }
 
     @Suppress("UNCHECKED_CAST")
-    fun Input.readMetaItem(): MetaItem<MetaBuilder> {
+    public fun Input.readMetaItem(): MetaItem<MetaBuilder> {
         return when (val keyChar = readByte().toChar()) {
             'S' -> MetaItem.ValueItem(StringValue(readString()))
             'N' -> MetaItem.ValueItem(Null)
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt
index ba03e2ed..992a080f 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt
@@ -4,64 +4,66 @@ import hep.dataforge.meta.Laminate
 import hep.dataforge.meta.Meta
 import hep.dataforge.meta.get
 import hep.dataforge.meta.string
+import hep.dataforge.names.Name
 import hep.dataforge.names.asName
 import hep.dataforge.names.plus
 import kotlinx.io.Binary
 
-interface Envelope {
-    val meta: Meta
-    val data: Binary?
+public interface Envelope {
+    public val meta: Meta
+    public val data: Binary?
 
-    companion object {
+    public companion object {
 
         /**
          * meta keys
          */
-        val ENVELOPE_NODE_KEY = "@envelope".asName()
-        val ENVELOPE_TYPE_KEY = ENVELOPE_NODE_KEY + "type"
-        val ENVELOPE_DATA_TYPE_KEY = ENVELOPE_NODE_KEY + "dataType"
-        val ENVELOPE_DATA_ID_KEY = ENVELOPE_NODE_KEY + "dataID"
-        val ENVELOPE_DESCRIPTION_KEY = ENVELOPE_NODE_KEY + "description"
-        val ENVELOPE_NAME_KEY = ENVELOPE_NODE_KEY + "name"
+        public val ENVELOPE_NODE_KEY: Name = "@envelope".asName()
+        public val ENVELOPE_TYPE_KEY: Name = ENVELOPE_NODE_KEY + "type"
+        public val ENVELOPE_DATA_TYPE_KEY: Name = ENVELOPE_NODE_KEY + "dataType"
+        public val ENVELOPE_DATA_ID_KEY: Name = ENVELOPE_NODE_KEY + "dataID"
+        public val ENVELOPE_DESCRIPTION_KEY: Name = ENVELOPE_NODE_KEY + "description"
+        public val ENVELOPE_NAME_KEY: Name = ENVELOPE_NODE_KEY + "name"
         //const val ENVELOPE_TIME_KEY = "@envelope.time"
 
         /**
          * Build a static envelope using provided builder
          */
-        inline operator fun invoke(block: EnvelopeBuilder.() -> Unit) = EnvelopeBuilder().apply(block).seal()
+        public inline operator fun invoke(block: EnvelopeBuilder.() -> Unit): Envelope =
+            EnvelopeBuilder().apply(block).seal()
     }
 }
 
-class SimpleEnvelope(override val meta: Meta, override val data: Binary?) : Envelope
+public class SimpleEnvelope(override val meta: Meta, override val data: Binary?) : Envelope
 
 /**
  * The purpose of the envelope
  *
  */
-val Envelope.type: String? get() = meta[Envelope.ENVELOPE_TYPE_KEY].string
+public val Envelope.type: String? get() = meta[Envelope.ENVELOPE_TYPE_KEY].string
 
 /**
  * The type of data encoding
  *
  */
-val Envelope.dataType: String? get() = meta[Envelope.ENVELOPE_DATA_TYPE_KEY].string
+public val Envelope.dataType: String? get() = meta[Envelope.ENVELOPE_DATA_TYPE_KEY].string
 
 /**
  * Textual user friendly description
  *
  */
-val Envelope.description: String? get() = meta[Envelope.ENVELOPE_DESCRIPTION_KEY].string
+public val Envelope.description: String? get() = meta[Envelope.ENVELOPE_DESCRIPTION_KEY].string
 
 /**
  * An optional unique identifier that is used for data comparison. Data without identifier could not be compared to another data.
  */
-val Envelope.dataID: String? get() = meta[Envelope.ENVELOPE_DATA_ID_KEY].string
+public val Envelope.dataID: String? get() = meta[Envelope.ENVELOPE_DATA_ID_KEY].string
 
-fun Envelope.metaEquals(other: Envelope): Boolean = this.meta == other.meta
+public fun Envelope.metaEquals(other: Envelope): Boolean = this.meta == other.meta
 
-fun Envelope.dataEquals(other: Envelope): Boolean = this.dataID != null && this.dataID == other.dataID
+public fun Envelope.dataEquals(other: Envelope): Boolean = this.dataID != null && this.dataID == other.dataID
 
-fun Envelope.contentEquals(other: Envelope): Boolean {
+public fun Envelope.contentEquals(other: Envelope): Boolean {
     return (this === other || (metaEquals(other) && dataEquals(other)))
 }
 
@@ -69,7 +71,7 @@ fun Envelope.contentEquals(other: Envelope): Boolean {
 /**
  * An envelope, which wraps existing envelope and adds one or several additional layers of meta
  */
-class ProxyEnvelope(val source: Envelope, vararg meta: Meta) : Envelope {
+public class ProxyEnvelope(public val source: Envelope, vararg meta: Meta) : Envelope {
     override val meta: Laminate = Laminate(*meta, source.meta)
     override val data: Binary? get() = source.data
 }
@@ -77,7 +79,7 @@ class ProxyEnvelope(val source: Envelope, vararg meta: Meta) : Envelope {
 /**
  * Add few meta layers to existing envelope (on top of existing meta)
  */
-fun Envelope.withMetaLayers(vararg layers: Meta): Envelope {
+public fun Envelope.withMetaLayers(vararg layers: Meta): Envelope {
     return when {
         layers.isEmpty() -> this
         this is ProxyEnvelope -> ProxyEnvelope(source, *layers, *this.meta.layers.toTypedArray())
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt
index 9b819a97..683f58f0 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt
@@ -13,31 +13,28 @@ import kotlin.reflect.KClass
 /**
  * A partially read envelope with meta, but without data
  */
-@ExperimentalUnsignedTypes
-data class PartialEnvelope(val meta: Meta, val dataOffset: UInt, val dataSize: ULong?)
+public data class PartialEnvelope(val meta: Meta, val dataOffset: UInt, val dataSize: ULong?)
 
-interface EnvelopeFormat : IOFormat<Envelope> {
-    val defaultMetaFormat: MetaFormatFactory get() = JsonMetaFormat
+public interface EnvelopeFormat : IOFormat<Envelope> {
+    public val defaultMetaFormat: MetaFormatFactory get() = JsonMetaFormat
 
-    fun Input.readPartial(): PartialEnvelope
+    public fun readPartial(input: Input): PartialEnvelope
 
-    fun Output.writeEnvelope(
+    public fun Output.writeEnvelope(
         envelope: Envelope,
         metaFormatFactory: MetaFormatFactory = defaultMetaFormat,
         formatMeta: Meta = Meta.EMPTY
     )
 
-    override fun Input.readObject(): Envelope
+    override fun readObject(input: Input): Envelope
 
-    override fun Output.writeObject(obj: Envelope): Unit = writeEnvelope(obj)
+    override fun writeObject(output: Output, obj: Envelope): Unit = output.writeEnvelope(obj)
 }
 
-fun EnvelopeFormat.readPartial(input: Input) = input.readPartial()
-
-fun EnvelopeFormat.read(input: Input) = input.readObject()
+public fun EnvelopeFormat.read(input: Input): Envelope = readObject(input)
 
 @Type(ENVELOPE_FORMAT_TYPE)
-interface EnvelopeFormatFactory : IOFormatFactory<Envelope>, EnvelopeFormat {
+public interface EnvelopeFormatFactory : IOFormatFactory<Envelope>, EnvelopeFormat {
     override val name: Name get() = "envelope".asName()
     override val type: KClass<out Envelope> get() = Envelope::class
 
@@ -47,9 +44,9 @@ interface EnvelopeFormatFactory : IOFormatFactory<Envelope>, EnvelopeFormat {
      * Try to infer specific format from input and return null if the attempt is failed.
      * This method does **not** return Input into initial state.
      */
-    fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat?
+    public fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat?
 
-    companion object {
-        const val ENVELOPE_FORMAT_TYPE = "io.format.envelope"
+    public companion object {
+        public const val ENVELOPE_FORMAT_TYPE: String = "io.format.envelope"
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt
index 19ccb458..805a91b3 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt
@@ -31,11 +31,11 @@ private class PartDescriptor : Scheme() {
     }
 }
 
-data class EnvelopePart(val binary: Binary, val description: Meta?)
+public data class EnvelopePart(val binary: Binary, val description: Meta?)
 
-typealias EnvelopeParts = List<EnvelopePart>
+public typealias EnvelopeParts = List<EnvelopePart>
 
-fun EnvelopeBuilder.multipart(
+public fun EnvelopeBuilder.multipart(
     parts: EnvelopeParts,
     separator: String = DEFAULT_MULTIPART_DATA_SEPARATOR
 ) {
@@ -69,7 +69,7 @@ fun EnvelopeBuilder.multipart(
     }
 }
 
-fun EnvelopeBuilder.envelopes(
+public fun EnvelopeBuilder.envelopes(
     envelopes: List<Envelope>,
     format: EnvelopeFormat = TaggedEnvelopeFormat,
     separator: String = DEFAULT_MULTIPART_DATA_SEPARATOR
@@ -84,7 +84,7 @@ fun EnvelopeBuilder.envelopes(
     multipart(parts, separator)
 }
 
-fun Envelope.parts(): EnvelopeParts {
+public fun Envelope.parts(): EnvelopeParts {
     if (data == null) return emptyList()
     //TODO add zip folder reader
     val parts = meta.getIndexed(PARTS_KEY).values.mapNotNull { it.node }.map {
@@ -101,14 +101,14 @@ fun Envelope.parts(): EnvelopeParts {
     }
 }
 
-fun EnvelopePart.envelope(format: EnvelopeFormat): Envelope = binary.readWith(format)
+public fun EnvelopePart.envelope(format: EnvelopeFormat): Envelope = binary.readWith(format)
 
-val EnvelopePart.name: String? get() = description?.get("name").string
+public val EnvelopePart.name: String? get() = description?.get("name").string
 
 /**
  * Represent envelope part by an envelope
  */
-fun EnvelopePart.envelope(plugin: IOPlugin): Envelope {
+public fun EnvelopePart.envelope(plugin: IOPlugin): Envelope {
     val formatItem = description?.get(PART_FORMAT_KEY)
     return if (formatItem != null) {
         val format: EnvelopeFormat = plugin.resolveEnvelopeFormat(formatItem)
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt
index 7946c536..281381d6 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt
@@ -20,41 +20,42 @@ import kotlin.reflect.KClass
 /**
  * And interface for reading and writing objects into with IO streams
  */
-interface IOFormat<T : Any> : MetaRepr {
-    fun Output.writeObject(obj: T)
-    fun Input.readObject(): T
+public interface IOFormat<T : Any> : MetaRepr {
+    public fun writeObject(output: Output, obj: T)
+    public fun readObject(input: Input): T
 
-    companion object{
-        val NAME_KEY = "name".asName()
-        val META_KEY = "meta".asName()
+    public companion object {
+        public val NAME_KEY: Name = "name".asName()
+        public val META_KEY: Name = "meta".asName()
     }
 }
 
-fun <T : Any> Input.readWith(format: IOFormat<T>): T = format.run { readObject() }
+public fun <T : Any> Input.readWith(format: IOFormat<T>): T = format.run { readObject(this@readWith) }
 
 /**
  * Read given binary as object using given format
  */
-fun <T : Any> Binary.readWith(format: IOFormat<T>): T = read {
+public fun <T : Any> Binary.readWith(format: IOFormat<T>): T = read {
     readWith(format)
 }
 
-fun <T : Any> Output.writeWith(format: IOFormat<T>, obj: T) = format.run { writeObject(obj) }
+public fun <T : Any> Output.writeWith(format: IOFormat<T>, obj: T): Unit =
+    format.run { writeObject(this@writeWith, obj) }
 
-class ListIOFormat<T : Any>(val format: IOFormat<T>) : IOFormat<List<T>> {
-    override fun Output.writeObject(obj: List<T>) {
-        writeInt(obj.size)
-        format.run {
+public class ListIOFormat<T : Any>(public val format: IOFormat<T>) : IOFormat<List<T>> {
+    override fun writeObject(output: Output, obj: List<T>) {
+        output.writeInt(obj.size)
+        this.format.run {
             obj.forEach {
-                writeObject(it)
+                writeObject(output, it)
             }
         }
     }
 
-    override fun Input.readObject(): List<T> {
-        val size = readInt()
+    override fun readObject(input: Input): List<T> {
+        val size = input.readInt()
         return format.run {
-            List(size) { readObject() }
+            List(size) { readObject(input) }
         }
     }
 
@@ -64,9 +65,9 @@ class ListIOFormat<T : Any>(val format: IOFormat<T>) : IOFormat<List<T>> {
     }
 }
 
-val <T : Any> IOFormat<T>.list get() = ListIOFormat(this)
+//public val <T : Any> IOFormat<T>.list: ListIOFormat<T> get() = ListIOFormat(this)
 
-fun ObjectPool<Buffer>.fill(block: Buffer.() -> Unit): Buffer {
+public fun ObjectPool<Buffer>.fill(block: Buffer.() -> Unit): Buffer {
     val buffer = borrow()
     return try {
         buffer.apply(block)
@@ -77,50 +78,50 @@ fun ObjectPool<Buffer>.fill(block: Buffer.() -> Unit): Buffer {
 }
 
 @Type(IO_FORMAT_TYPE)
-interface IOFormatFactory<T : Any> : Factory<IOFormat<T>>, Named, MetaRepr {
+public interface IOFormatFactory<T : Any> : Factory<IOFormat<T>>, Named, MetaRepr {
     /**
      * Explicit type for dynamic type checks
      */
-    val type: KClass<out T>
+    public val type: KClass<out T>
 
     override fun toMeta(): Meta = Meta {
         NAME_KEY put name.toString()
     }
 
-    companion object {
-        const val IO_FORMAT_TYPE = "io.format"
+    public companion object {
+        public const val IO_FORMAT_TYPE: String = "io.format"
     }
 }
 
-fun <T : Any> IOFormat<T>.toBinary(obj: T): Binary = Binary { writeObject(obj) }
+public fun <T : Any> IOFormat<T>.toBinary(obj: T): Binary = Binary { writeObject(this, obj) }
 
-object DoubleIOFormat : IOFormat<Double>, IOFormatFactory<Double> {
+public object DoubleIOFormat : IOFormat<Double>, IOFormatFactory<Double> {
     override fun invoke(meta: Meta, context: Context): IOFormat<Double> = this
 
     override val name: Name = "double".asName()
 
     override val type: KClass<out Double> get() = Double::class
 
-    override fun Output.writeObject(obj: Double) {
-        writeDouble(obj)
+    override fun writeObject(output: Output, obj: kotlin.Double) {
+        output.writeDouble(obj)
     }
 
-    override fun Input.readObject(): Double = readDouble()
+    override fun readObject(input: Input): Double = input.readDouble()
 }
 
-object ValueIOFormat : IOFormat<Value>, IOFormatFactory<Value> {
+public object ValueIOFormat : IOFormat<Value>, IOFormatFactory<Value> {
     override fun invoke(meta: Meta, context: Context): IOFormat<Value> = this
 
     override val name: Name = "value".asName()
 
     override val type: KClass<out Value> get() = Value::class
 
-    override fun Output.writeObject(obj: Value) {
-        BinaryMetaFormat.run { writeValue(obj) }
+    override fun writeObject(output: Output, obj: Value) {
+        BinaryMetaFormat.run { output.writeValue(obj) }
     }
 
-    override fun Input.readObject(): Value {
-        return (BinaryMetaFormat.run { readMetaItem() } as? MetaItem.ValueItem)?.value
+    override fun readObject(input: Input): Value {
+        return (BinaryMetaFormat.run { input.readMetaItem() } as? MetaItem.ValueItem)?.value
             ?: error("The item is not a value")
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt
index 73fd26f1..f1684ce8 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt
@@ -11,14 +11,14 @@ import hep.dataforge.names.Name
 import hep.dataforge.names.toName
 import kotlin.reflect.KClass
 
-class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
+public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
     override val tag: PluginTag get() = Companion.tag
 
-    val ioFormatFactories by lazy {
-        context.content<IOFormatFactory<*>>(IO_FORMAT_TYPE).values
+    public val ioFormatFactories: Collection<IOFormatFactory<*>> by lazy {
+        context.resolve<IOFormatFactory<*>>(IO_FORMAT_TYPE).values
     }
 
-    fun <T : Any> resolveIOFormat(item: MetaItem<*>, type: KClass<out T>): IOFormat<T>? {
+    public fun <T : Any> resolveIOFormat(item: MetaItem<*>, type: KClass<out T>): IOFormat<T>? {
         val key = item.string ?: item.node[NAME_KEY]?.string ?: error("Format name not defined")
         val name = key.toName()
         return ioFormatFactories.find { it.name == name }?.let {
@@ -29,24 +29,24 @@ class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
     }
 
 
-    val metaFormatFactories by lazy {
-        context.content<MetaFormatFactory>(META_FORMAT_TYPE).values
+    public val metaFormatFactories: Collection<MetaFormatFactory> by lazy {
+        context.resolve<MetaFormatFactory>(META_FORMAT_TYPE).values
     }
 
-    fun resolveMetaFormat(key: Short, meta: Meta = Meta.EMPTY): MetaFormat? =
+    public fun resolveMetaFormat(key: Short, meta: Meta = Meta.EMPTY): MetaFormat? =
         metaFormatFactories.find { it.key == key }?.invoke(meta)
 
-    fun resolveMetaFormat(name: String, meta: Meta = Meta.EMPTY): MetaFormat? =
+    public fun resolveMetaFormat(name: String, meta: Meta = Meta.EMPTY): MetaFormat? =
         metaFormatFactories.find { it.shortName == name }?.invoke(meta)
 
-    val envelopeFormatFactories by lazy {
-        context.content<EnvelopeFormatFactory>(ENVELOPE_FORMAT_TYPE).values
+    public val envelopeFormatFactories: Collection<EnvelopeFormatFactory> by lazy {
+        context.resolve<EnvelopeFormatFactory>(ENVELOPE_FORMAT_TYPE).values
     }
 
-    fun resolveEnvelopeFormat(name: Name, meta: Meta = Meta.EMPTY): EnvelopeFormat? =
+    private fun resolveEnvelopeFormat(name: Name, meta: Meta = Meta.EMPTY): EnvelopeFormat? =
         envelopeFormatFactories.find { it.name == name }?.invoke(meta, context)
 
-    fun resolveEnvelopeFormat(item: MetaItem<*>): EnvelopeFormat? {
+    public fun resolveEnvelopeFormat(item: MetaItem<*>): EnvelopeFormat? {
         val name = item.string ?: item.node[NAME_KEY]?.string ?: error("Envelope format name not defined")
         val meta = item.node[META_KEY].node ?: Meta.EMPTY
         return resolveEnvelopeFormat(name.toName(), meta)
@@ -60,9 +60,9 @@ class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
         }
     }
 
-    companion object : PluginFactory<IOPlugin> {
-        val defaultMetaFormats: List<MetaFormatFactory> = listOf(JsonMetaFormat, BinaryMetaFormat)
-        val defaultEnvelopeFormats = listOf(TaggedEnvelopeFormat, TaglessEnvelopeFormat)
+    public companion object : PluginFactory<IOPlugin> {
+        public val defaultMetaFormats: List<MetaFormatFactory> = listOf(JsonMetaFormat, BinaryMetaFormat)
+        public val defaultEnvelopeFormats: List<EnvelopeFormatFactory> = listOf(TaggedEnvelopeFormat, TaglessEnvelopeFormat)
 
         override val tag: PluginTag = PluginTag("io", group = PluginTag.DATAFORGE_GROUP)
 
@@ -71,4 +71,4 @@ class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
     }
 }
 
-val Context.io: IOPlugin get() = plugins.fetch(IOPlugin)
\ No newline at end of file
+public val Context.io: IOPlugin get() = plugins.fetch(IOPlugin)
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
index 96fab099..aba20e9c 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
@@ -17,39 +17,41 @@ import kotlinx.io.text.writeUtf8String
 import kotlinx.serialization.json.Json
 import kotlinx.serialization.json.JsonObject
 
+/**
+ * A Json format for Meta representation
+ */
+public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat {
 
-class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat {
-
-    override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) {
+    override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) {
         val jsonObject = meta.toJson(descriptor)
-        writeUtf8String(json.encodeToString(JsonObject.serializer(), jsonObject))
+        output.writeUtf8String(this.json.encodeToString(JsonObject.serializer(), jsonObject))
     }
 
     override fun toMeta(): Meta = Meta {
         NAME_KEY put name.toString()
     }
 
-    override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
-        val str = readByteArray().decodeToString()
+    override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
+        val str = input.readByteArray().decodeToString()
         val jsonElement = json.parseToJsonElement(str)
         val item = jsonElement.toMetaItem(descriptor)
         return item.node ?: Meta.EMPTY
     }
 
-    companion object : MetaFormatFactory {
-        val DEFAULT_JSON = Json { prettyPrint = true }
+    public companion object : MetaFormatFactory {
+        public val DEFAULT_JSON: Json = Json { prettyPrint = true }
 
         override fun invoke(meta: Meta, context: Context): MetaFormat = default
 
-        override val shortName = "json"
+        override val shortName: String = "json"
         override val key: Short = 0x4a53//"JS"
 
         private val default = JsonMetaFormat()
 
-        override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) =
-            default.run { writeMeta(meta, descriptor) }
+        override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?): Unit =
+            default.run { writeMeta(output, meta, descriptor) }
 
-        override fun Input.readMeta(descriptor: NodeDescriptor?): Meta =
-            default.run { readMeta(descriptor) }
+        override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta =
+            default.run { readMeta(input, descriptor) }
     }
 }
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/MetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/MetaFormat.kt
index 4b893a4a..f3e26d2a 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/MetaFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/MetaFormat.kt
@@ -17,46 +17,50 @@ import kotlin.reflect.KClass
 /**
  * A format for meta serialization
  */
+public interface MetaFormat : IOFormat<Meta> {
 
-interface MetaFormat : IOFormat<Meta> {
-
-    override fun Output.writeObject(obj: Meta) {
-        writeMeta(obj, null)
+    override fun writeObject(output: Output, obj: Meta) {
+        writeMeta(output, obj, null)
     }
 
-    override fun Input.readObject(): Meta = readMeta()
+    override fun readObject(input: Input): Meta = readMeta(input)
 
-    fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor? = null)
-    fun Input.readMeta(descriptor: NodeDescriptor? = null): Meta
+    public fun writeMeta(
+        output: Output,
+        meta: Meta,
+        descriptor: NodeDescriptor? = null,
+    )
+
+    public fun readMeta(input: Input, descriptor: NodeDescriptor? = null): Meta
 }
 
 @Type(META_FORMAT_TYPE)
-interface MetaFormatFactory : IOFormatFactory<Meta>, MetaFormat {
-    val shortName: String
+public interface MetaFormatFactory : IOFormatFactory<Meta>, MetaFormat {
+    public val shortName: String
 
     override val name: Name get() = "meta".asName() + shortName
 
     override val type: KClass<out Meta> get() = Meta::class
 
-    val key: Short get() = name.hashCode().toShort()
+    public val key: Short get() = name.hashCode().toShort()
 
     override operator fun invoke(meta: Meta, context: Context): MetaFormat
 
-    companion object {
-        const val META_FORMAT_TYPE = "io.format.meta"
+    public companion object {
+        public const val META_FORMAT_TYPE: String = "io.format.meta"
     }
 }
 
-fun Meta.toString(format: MetaFormat): String = buildByteArray {
-    format.run { writeObject(this@toString) }
+public fun Meta.toString(format: MetaFormat): String = buildByteArray {
+    format.run { writeObject(this@buildByteArray, this@toString) }
 }.decodeToString()
 
-fun Meta.toString(formatFactory: MetaFormatFactory): String = toString(formatFactory())
+public fun Meta.toString(formatFactory: MetaFormatFactory): String = toString(formatFactory())
 
-fun MetaFormat.parse(str: String): Meta {
-    return ByteArrayInput(str.encodeToByteArray()).use { it.readObject() }
+public fun MetaFormat.parse(str: String): Meta {
+    return ByteArrayInput(str.encodeToByteArray()).use { readObject(it) }
 }
 
-fun MetaFormatFactory.parse(str: String, formatMeta: Meta): Meta = invoke(formatMeta).parse(str)
+public fun MetaFormatFactory.parse(str: String, formatMeta: Meta): Meta = invoke(formatMeta).parse(str)
 
 
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
index ebcca243..19c58910 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
@@ -12,9 +12,13 @@ import hep.dataforge.names.plus
 import hep.dataforge.names.toName
 import kotlinx.io.*
 
-class TaggedEnvelopeFormat(
-    val io: IOPlugin,
-    val version: VERSION = VERSION.DF02
+/**
+ * A streaming-friendly envelope format with a short binary tag.
+ * TODO add description
+ */
+public class TaggedEnvelopeFormat(
+    public val io: IOPlugin,
+    public val version: VERSION = VERSION.DF02
 ) : EnvelopeFormat {
 
 //    private val metaFormat = io.metaFormat(metaFormatKey)
@@ -57,32 +61,32 @@ class TaggedEnvelopeFormat(
      * @param input an input to read from
      * @param formats a collection of meta formats to resolve
      */
-    override fun Input.readObject(): Envelope {
-        val tag = readTag(version)
+    override fun readObject(input: Input): Envelope {
+        val tag = input.readTag(this.version)
 
         val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
             ?: error("Meta format with key ${tag.metaFormatKey} not found")
 
-        val meta: Meta = limit(tag.metaSize.toInt()).run {
+        val meta: Meta = input.limit(tag.metaSize.toInt()).run {
             metaFormat.run {
-                readObject()
+                readObject(input)
             }
         }
 
-        val data = readBinary(tag.dataSize.toInt())
+        val data = input.readBinary(tag.dataSize.toInt())
 
         return SimpleEnvelope(meta, data)
     }
 
-    override fun Input.readPartial(): PartialEnvelope {
-        val tag = readTag(version)
+    override fun readPartial(input: Input): PartialEnvelope {
+        val tag = input.readTag(this.version)
 
         val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
             ?: error("Meta format with key ${tag.metaFormatKey} not found")
 
-        val meta: Meta = limit(tag.metaSize.toInt()).run {
+        val meta: Meta = input.limit(tag.metaSize.toInt()).run {
             metaFormat.run {
-                readObject()
+                readObject(input)
             }
         }
 
@@ -95,7 +99,7 @@ class TaggedEnvelopeFormat(
         val dataSize: ULong
     )
 
-    enum class VERSION(val tagSize: UInt) {
+    public enum class VERSION(public val tagSize: UInt) {
         DF02(20u),
         DF03(24u)
     }
@@ -107,7 +111,7 @@ class TaggedEnvelopeFormat(
         }
     }
 
-    companion object : EnvelopeFormatFactory {
+    public companion object : EnvelopeFormatFactory {
         private const val START_SEQUENCE = "#~"
         private const val END_SEQUENCE = "~#\r\n"
 
@@ -158,14 +162,14 @@ class TaggedEnvelopeFormat(
 
         private val default by lazy { invoke() }
 
-        override fun Input.readPartial(): PartialEnvelope =
-            default.run { readPartial() }
+        override fun readPartial(input: Input): PartialEnvelope =
+            default.run { readPartial(input) }
 
-        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) =
+        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
             default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
 
-        override fun Input.readObject(): Envelope =
-            default.run { readObject() }
+        override fun readObject(input: Input): Envelope =
+            default.run { readObject(input) }
 
 
     }
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
index c800d878..593e0a95 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
@@ -7,15 +7,20 @@ import hep.dataforge.meta.Meta
 import hep.dataforge.meta.get
 import hep.dataforge.meta.isEmpty
 import hep.dataforge.meta.string
+import hep.dataforge.names.Name
 import hep.dataforge.names.asName
 import kotlinx.io.*
 import kotlinx.io.text.readUtf8Line
 import kotlinx.io.text.writeUtf8String
 import kotlin.collections.set
 
-class TaglessEnvelopeFormat(
-    val io: IOPlugin,
-    val meta: Meta = Meta.EMPTY
+/**
+ * A text envelope format with human-readable tag.
+ * TODO add description
+ */
+public class TaglessEnvelopeFormat(
+    public val io: IOPlugin,
+    public val meta: Meta = Meta.EMPTY
 ) : EnvelopeFormat {
 
     private val metaStart = meta[META_START_PROPERTY].string ?: DEFAULT_META_START
@@ -54,10 +59,10 @@ class TaglessEnvelopeFormat(
         }
     }
 
-    override fun Input.readObject(): Envelope {
+    override fun readObject(input: Input): Envelope {
         var line: String
         do {
-            line = readUtf8Line() // ?: error("Input does not contain tagless envelope header")
+            line = input.readUtf8Line() // ?: error("Input does not contain tagless envelope header")
         } while (!line.startsWith(TAGLESS_ENVELOPE_HEADER))
         val properties = HashMap<String, String>()
 
@@ -70,8 +75,8 @@ class TaglessEnvelopeFormat(
                 properties[key] = value
             }
             //If can't read line, return envelope without data
-            if (exhausted()) return SimpleEnvelope(Meta.EMPTY, null)
-            line = readUtf8Line()
+            if (input.exhausted()) return SimpleEnvelope(Meta.EMPTY, null)
+            line = input.readUtf8Line()
         }
 
         var meta: Meta = Meta.EMPTY
@@ -80,19 +85,19 @@ class TaglessEnvelopeFormat(
             val metaFormat = properties[META_TYPE_PROPERTY]?.let { io.resolveMetaFormat(it) } ?: JsonMetaFormat
             val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
             meta = if (metaSize != null) {
-                limit(metaSize).run {
-                    metaFormat.run { readObject() }
+                input.limit(metaSize).run {
+                    metaFormat.run { readObject(input) }
                 }
             } else {
                 metaFormat.run {
-                    readObject()
+                    readObject(input)
                 }
             }
         }
 
         do {
             try {
-                line = readUtf8Line()
+                line = input.readUtf8Line()
             } catch (ex: EOFException) {
                 //returning an Envelope without data if end of input is reached
                 return SimpleEnvelope(meta, null)
@@ -100,24 +105,24 @@ class TaglessEnvelopeFormat(
         } while (!line.startsWith(dataStart))
 
         val data: Binary? = if (properties.containsKey(DATA_LENGTH_PROPERTY)) {
-            readBinary(properties[DATA_LENGTH_PROPERTY]!!.toInt())
+            input.readBinary(properties[DATA_LENGTH_PROPERTY]!!.toInt())
 //            val bytes = ByteArray(properties[DATA_LENGTH_PROPERTY]!!.toInt())
 //            readByteArray(bytes)
 //            bytes.asBinary()
         } else {
             Binary {
-                copyTo(this)
+                input.copyTo(this)
             }
         }
 
         return SimpleEnvelope(meta, data)
     }
 
-    override fun Input.readPartial(): PartialEnvelope {
+    override fun readPartial(input: Input): PartialEnvelope {
         var offset = 0u
         var line: String
         do {
-            line = readUtf8Line()// ?: error("Input does not contain tagless envelope header")
+            line = input.readUtf8Line()// ?: error("Input does not contain tagless envelope header")
             offset += line.encodeToByteArray().size.toUInt()
         } while (!line.startsWith(TAGLESS_ENVELOPE_HEADER))
         val properties = HashMap<String, String>()
@@ -131,7 +136,7 @@ class TaglessEnvelopeFormat(
                 properties[key] = value
             }
             try {
-                line = readUtf8Line()
+                line = input.readUtf8Line()
                 offset += line.encodeToByteArray().size.toUInt()
             } catch (ex: EOFException) {
                 return PartialEnvelope(Meta.EMPTY, offset.toUInt(), 0.toULong())
@@ -145,8 +150,8 @@ class TaglessEnvelopeFormat(
             val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
             meta = if (metaSize != null) {
                 offset += metaSize.toUInt()
-                limit(metaSize).run {
-                    metaFormat.run { readObject() }
+                input.limit(metaSize).run {
+                    metaFormat.run { readObject(input) }
                 }
             } else {
                 error("Can't partially read an envelope with undefined meta size")
@@ -154,7 +159,7 @@ class TaglessEnvelopeFormat(
         }
 
         do {
-            line = readUtf8Line() //?: return PartialEnvelope(Meta.EMPTY, offset.toUInt(), 0.toULong())
+            line = input.readUtf8Line() //?: return PartialEnvelope(Meta.EMPTY, offset.toUInt(), 0.toULong())
             offset += line.encodeToByteArray().size.toUInt()
             //returning an Envelope without data if end of input is reached
         } while (!line.startsWith(dataStart))
@@ -168,26 +173,26 @@ class TaglessEnvelopeFormat(
         META_KEY put meta
     }
 
-    companion object : EnvelopeFormatFactory {
+    public companion object : EnvelopeFormatFactory {
 
         private val propertyPattern = "#\\?\\s*(?<key>[\\w.]*)\\s*:\\s*(?<value>[^;]*);?".toRegex()
 
-        const val META_TYPE_PROPERTY = "metaType"
-        const val META_LENGTH_PROPERTY = "metaLength"
-        const val DATA_LENGTH_PROPERTY = "dataLength"
+        public const val META_TYPE_PROPERTY: String = "metaType"
+        public const val META_LENGTH_PROPERTY: String = "metaLength"
+        public const val DATA_LENGTH_PROPERTY: String = "dataLength"
 
 
-        const val TAGLESS_ENVELOPE_TYPE = "tagless"
+        public const val TAGLESS_ENVELOPE_TYPE: String = "tagless"
 
-        const val TAGLESS_ENVELOPE_HEADER = "#~DFTL~#"
-        const val META_START_PROPERTY = "metaSeparator"
-        const val DEFAULT_META_START = "#~META~#"
-        const val DATA_START_PROPERTY = "dataSeparator"
-        const val DEFAULT_DATA_START = "#~DATA~#"
+        public const val TAGLESS_ENVELOPE_HEADER: String = "#~DFTL~#"
+        public const val META_START_PROPERTY: String = "metaSeparator"
+        public const val DEFAULT_META_START: String = "#~META~#"
+        public const val DATA_START_PROPERTY: String = "dataSeparator"
+        public const val DEFAULT_DATA_START: String = "#~DATA~#"
 
-        const val code: Int = 0x4446544c //DFTL
+        public const val code: Int = 0x4446544c //DFTL
 
-        override val name = TAGLESS_ENVELOPE_TYPE.asName()
+        override val name: Name = TAGLESS_ENVELOPE_TYPE.asName()
 
         override fun invoke(meta: Meta, context: Context): EnvelopeFormat {
             return TaglessEnvelopeFormat(context.io, meta)
@@ -195,14 +200,14 @@ class TaglessEnvelopeFormat(
 
         private val default by lazy { invoke() }
 
-        override fun Input.readPartial(): PartialEnvelope =
-            default.run { readPartial() }
+        override fun readPartial(input: Input): PartialEnvelope =
+            default.run { readPartial(input) }
 
-        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) =
+        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
             default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
 
-        override fun Input.readObject(): Envelope =
-            default.run { readObject() }
+        override fun readObject(input: Input): Envelope =
+            default.run { readObject(input) }
 
         override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? {
             return try {
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt
index 247f937e..cb8ba54b 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt
@@ -8,11 +8,11 @@ import kotlin.test.Test
 import kotlin.test.assertEquals
 
 fun Meta.toByteArray(format: MetaFormat = JsonMetaFormat) = buildByteArray {
-    format.run { writeObject(this@toByteArray) }
+    format.writeObject(this@buildByteArray, this@toByteArray)
 }
 
 fun MetaFormat.fromByteArray(packet: ByteArray): Meta {
-    return packet.asBinary().read { readObject() }
+    return packet.asBinary().read { readObject(this) }
 }
 
 class MetaFormatTest {
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt
index 2694ff8f..d27dc9da 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt
@@ -3,5 +3,5 @@ package hep.dataforge.io
 import kotlinx.io.ByteArrayInput
 import kotlinx.io.use
 
-fun <T : Any> IOFormat<T>.toByteArray(obj: T): ByteArray = buildByteArray { writeObject(obj) }
-fun <T : Any> IOFormat<T>.readByteArray(array: ByteArray): T = ByteArrayInput(array).use { it.readObject() }
\ No newline at end of file
+fun <T : Any> IOFormat<T>.toByteArray(obj: T): ByteArray = buildByteArray { writeObject(this, obj) }
+fun <T : Any> IOFormat<T>.readByteArray(array: ByteArray): T = ByteArrayInput(array).use { readObject(it) }
\ No newline at end of file
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
index 044cf932..19c7a14d 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
@@ -11,12 +11,12 @@ import java.nio.file.StandardOpenOption
 import kotlin.reflect.full.isSuperclassOf
 import kotlin.streams.asSequence
 
-fun <R> Path.read(block: Input.() -> R): R = asBinary().read(block = block)
+public fun <R> Path.read(block: Input.() -> R): R = asBinary().read(block = block)
 
 /**
  * Write a live output to a newly created file. If file does not exist, throws error
  */
-fun Path.write(block: Output.() -> Unit): Unit {
+public fun Path.write(block: Output.() -> Unit): Unit {
     val stream = Files.newOutputStream(this, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)
     stream.asOutput().use(block)
 }
@@ -24,7 +24,7 @@ fun Path.write(block: Output.() -> Unit): Unit {
 /**
  * Create a new file or append to exiting one with given output [block]
  */
-fun Path.append(block: Output.() -> Unit): Unit {
+public fun Path.append(block: Output.() -> Unit): Unit {
     val stream = Files.newOutputStream(
         this,
         StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE
@@ -35,7 +35,7 @@ fun Path.append(block: Output.() -> Unit): Unit {
 /**
  * Create a new file or replace existing one using given output [block]
  */
-fun Path.rewrite(block: Output.() -> Unit): Unit {
+public fun Path.rewrite(block: Output.() -> Unit): Unit {
     val stream = Files.newOutputStream(
         this,
         StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE
@@ -43,9 +43,9 @@ fun Path.rewrite(block: Output.() -> Unit): Unit {
     stream.asOutput().use(block)
 }
 
-fun Path.readEnvelope(format: EnvelopeFormat): Envelope {
+public fun Path.readEnvelope(format: EnvelopeFormat): Envelope {
     val partialEnvelope: PartialEnvelope = asBinary().read {
-        format.run { readPartial() }
+        format.run { readPartial(this@read) }
     }
     val offset: Int = partialEnvelope.dataOffset.toInt()
     val size: Int = partialEnvelope.dataSize?.toInt() ?: (Files.size(this).toInt() - offset)
@@ -58,7 +58,7 @@ fun Path.readEnvelope(format: EnvelopeFormat): Envelope {
  */
 @Suppress("UNCHECKED_CAST")
 @DFExperimental
-inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? {
+public inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? {
     return ioFormatFactories.find { it.type.isSuperclassOf(T::class) } as IOFormat<T>?
 }
 
@@ -66,7 +66,7 @@ inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? {
  * Read file containing meta using given [formatOverride] or file extension to infer meta type.
  * If [path] is a directory search for file starting with `meta` in it
  */
-fun IOPlugin.readMetaFile(path: Path, formatOverride: MetaFormat? = null, descriptor: NodeDescriptor? = null): Meta {
+public fun IOPlugin.readMetaFile(path: Path, formatOverride: MetaFormat? = null, descriptor: NodeDescriptor? = null): Meta {
     if (!Files.exists(path)) error("Meta file $path does not exist")
 
     val actualPath: Path = if (Files.isDirectory(path)) {
@@ -80,7 +80,7 @@ fun IOPlugin.readMetaFile(path: Path, formatOverride: MetaFormat? = null, descri
     val metaFormat = formatOverride ?: resolveMetaFormat(extension) ?: error("Can't resolve meta format $extension")
     return metaFormat.run {
         actualPath.read {
-            readMeta(descriptor)
+            readMeta(this, descriptor)
         }
     }
 }
@@ -89,7 +89,7 @@ fun IOPlugin.readMetaFile(path: Path, formatOverride: MetaFormat? = null, descri
  * Write meta to file using [metaFormat]. If [path] is a directory, write a file with name equals name of [metaFormat].
  * Like "meta.json"
  */
-fun IOPlugin.writeMetaFile(
+public fun IOPlugin.writeMetaFile(
     path: Path,
     meta: Meta,
     metaFormat: MetaFormatFactory = JsonMetaFormat,
@@ -102,7 +102,7 @@ fun IOPlugin.writeMetaFile(
     }
     metaFormat.run {
         actualPath.write {
-            writeMeta(meta, descriptor)
+            writeMeta(this, meta, descriptor)
         }
     }
 }
@@ -111,7 +111,7 @@ fun IOPlugin.writeMetaFile(
  * Return inferred [EnvelopeFormat] if only one format could read given file. If no format accepts file, return null. If
  * multiple formats accepts file, throw an error.
  */
-fun IOPlugin.peekBinaryFormat(path: Path): EnvelopeFormat? {
+public fun IOPlugin.peekBinaryFormat(path: Path): EnvelopeFormat? {
     val binary = path.asBinary()
     val formats = envelopeFormatFactories.mapNotNull { factory ->
         binary.read {
@@ -126,8 +126,8 @@ fun IOPlugin.peekBinaryFormat(path: Path): EnvelopeFormat? {
     }
 }
 
-val IOPlugin.Companion.META_FILE_NAME: String get() = "@meta"
-val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
+public val IOPlugin.Companion.META_FILE_NAME: String get() = "@meta"
+public val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
 
 /**
  * Read and envelope from file if the file exists, return null if file does not exist.
@@ -143,7 +143,7 @@ val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
  * Return null otherwise.
  */
 @DFExperimental
-fun IOPlugin.readEnvelopeFile(
+public fun IOPlugin.readEnvelopeFile(
     path: Path,
     readNonEnvelopes: Boolean = false,
     formatPeeker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat
@@ -182,9 +182,9 @@ fun IOPlugin.readEnvelopeFile(
 /**
  * Write a binary into file. Throws an error if file already exists
  */
-fun <T : Any> IOFormat<T>.writeToFile(path: Path, obj: T) {
+public fun <T : Any> IOFormat<T>.writeToFile(path: Path, obj: T) {
     path.write {
-        writeObject(obj)
+        writeObject(this, obj)
     }
 }
 
@@ -192,7 +192,7 @@ fun <T : Any> IOFormat<T>.writeToFile(path: Path, obj: T) {
  * Write envelope file to given [path] using [envelopeFormat] and optional [metaFormat]
  */
 @DFExperimental
-fun IOPlugin.writeEnvelopeFile(
+public fun IOPlugin.writeEnvelopeFile(
     path: Path,
     envelope: Envelope,
     envelopeFormat: EnvelopeFormat = TaggedEnvelopeFormat,
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
index 4e7a4243..f52b752c 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
@@ -56,10 +56,10 @@ public class EnvelopeClient(
         val outputStream = socket.getOutputStream()
         format.run {
             outputStream.write {
-                writeObject(request)
+                writeObject(this, request)
             }
             logger.debug { "Sent request with type ${request.type} to ${socket.remoteSocketAddress}" }
-            val res = inputStream.readBlocking { readObject() }
+            val res = inputStream.readBlocking { readObject(this) }
             logger.debug { "Received response with type ${res.type} from ${socket.remoteSocketAddress}" }
             return@withContext res
         }
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
index 3f83e841..9a6f2b0f 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
@@ -74,12 +74,12 @@ public class EnvelopeServer(
             val outputStream = socket.getOutputStream()
             format.run {
                 while (socket.isConnected) {
-                    val request = inputStream.readBlocking { readObject() }
+                    val request = inputStream.readBlocking { readObject(this) }
                     logger.debug { "Accepted request with type ${request.type} from ${socket.remoteSocketAddress}" }
                     if (request.type == SHUTDOWN_ENVELOPE_TYPE) {
                         //Echo shutdown command
                         outputStream.write {
-                            writeObject(request)
+                            writeObject(this, request)
                         }
                         logger.info { "Accepted graceful shutdown signal from ${socket.inetAddress}" }
                         socket.close()
@@ -89,7 +89,7 @@ public class EnvelopeServer(
                     runBlocking {
                         val response = responder.respond(request)
                         outputStream.write {
-                            writeObject(response)
+                            writeObject(this, response)
                         }
                         logger.debug { "Sent response with type ${response.type} to ${socket.remoteSocketAddress}" }
                     }
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
index c94fd8ca..5648a822 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
@@ -1,7 +1,7 @@
 package hep.dataforge.workspace
 
 import hep.dataforge.context.Context
-import hep.dataforge.context.content
+import hep.dataforge.context.resolve
 import hep.dataforge.context.toMap
 import hep.dataforge.data.DataNode
 import hep.dataforge.meta.Meta
@@ -19,7 +19,7 @@ class SimpleWorkspace(
 ) : Workspace {
 
     override val tasks: Map<Name, Task<*>> by lazy {
-        context.content<Task<*>>(Task.TYPE) + tasks.toMap()
+        context.resolve<Task<*>>(Task.TYPE) + tasks.toMap()
     }
 
     companion object {
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt
index 3bc1ffcf..a7da78e0 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt
@@ -27,7 +27,7 @@ interface WorkspaceBuilder {
  * Set the context for future workspcace
  */
 fun WorkspaceBuilder.context(name: String = "WORKSPACE", block: ContextBuilder.() -> Unit = {}) {
-    context = ContextBuilder(name, parentContext).apply(block).build()
+    context = ContextBuilder(parentContext, name).apply(block).build()
 }
 
 inline fun <reified T : Any> WorkspaceBuilder.data(
diff --git a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt b/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt
index 6d16c37d..4631dc09 100644
--- a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt
+++ b/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt
@@ -168,7 +168,7 @@ private suspend fun <T : Any> ZipOutputStream.writeNode(
                 val entry = ZipEntry(name)
                 putNextEntry(entry)
                 envelopeFormat.run {
-                    asOutput().writeObject(envelope)
+                    writeObject(asOutput(), envelope)
                 }
             }
             is DataItem.Node -> {
diff --git a/dataforge-workspace/src/jvmTest/kotlin/hep/dataforge/workspace/FileDataTest.kt b/dataforge-workspace/src/jvmTest/kotlin/hep/dataforge/workspace/FileDataTest.kt
index 6c9537cc..7357c5c5 100644
--- a/dataforge-workspace/src/jvmTest/kotlin/hep/dataforge/workspace/FileDataTest.kt
+++ b/dataforge-workspace/src/jvmTest/kotlin/hep/dataforge/workspace/FileDataTest.kt
@@ -30,12 +30,12 @@ class FileDataTest {
     }
 
     object StringIOFormat : IOFormat<String> {
-        override fun Output.writeObject(obj: String) {
-            writeUtf8String(obj)
+        override fun writeObject(output: Output, obj: String) {
+            output.writeUtf8String(obj)
         }
 
-        override fun Input.readObject(): String {
-            return readUtf8String()
+        override fun readObject(input: Input): String {
+            return input.readUtf8String()
         }
 
         override fun toMeta(): Meta = Meta {
diff --git a/settings.gradle.kts b/settings.gradle.kts
index b6f80363..b0b821fc 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -8,7 +8,7 @@ pluginManagement {
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
 
-    val toolsVersion = "0.6.0-dev-3"
+    val toolsVersion = "0.6.0-dev-4"
     val kotlinVersion = "1.4.0"
 
     plugins {

From 87af89b47db125e346009166b8f6d8a23b47a5fd Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Mon, 7 Sep 2020 16:19:57 +0300
Subject: [PATCH 16/40] Refactor MetaItem delegates.

---
 .../kotlin/hep/dataforge/meta/ItemDelegate.kt |  47 +++++--
 .../hep/dataforge/meta/MutableItemDelegate.kt | 131 ++++++++++++------
 .../hep/dataforge/meta/propertyConverter.kt   |  83 -----------
 settings.gradle.kts                           |   1 -
 4 files changed, 122 insertions(+), 140 deletions(-)
 delete mode 100644 dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/propertyConverter.kt

diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
index 830f4a2c..2201aa8a 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
@@ -5,26 +5,47 @@ import hep.dataforge.names.Name
 import hep.dataforge.names.asName
 import hep.dataforge.values.Value
 import kotlin.properties.ReadOnlyProperty
-import kotlin.reflect.KProperty
 
 /* Meta delegates */
-//TODO to be replaced in 1.4 by interfaces
-open class ItemDelegate(
-    open val owner: ItemProvider,
-    val key: Name? = null,
-    open val default: MetaItem<*>? = null
-) : ReadOnlyProperty<Any?, MetaItem<*>?> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*>? {
-        return owner.getItem(key ?: property.name.asName()) ?: default
-    }
-}
 
-public fun ItemProvider.item(key: Name? = null): ItemDelegate = ItemDelegate(this, key)
+public typealias ItemDelegate = ReadOnlyProperty<Any?, MetaItem<*>?>
+
+public fun ItemProvider.item(key: Name? = null): ItemDelegate = ReadOnlyProperty { _, property ->
+    getItem(key ?: property.name.asName())
+}
 
 //TODO add caching for sealed nodes
 
 
-//Read-only delegates for Metas
+/**
+ * Apply a converter to this delegate creating a delegate with a custom type
+ */
+public fun <R : Any> ItemDelegate.convert(
+    converter: MetaConverter<R>,
+): ReadOnlyProperty<Any?, R?> = ReadOnlyProperty { thisRef, property ->
+    this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
+}
+
+/*
+ *
+ */
+public fun <R : Any> ItemDelegate.convert(
+    converter: MetaConverter<R>,
+    default: () -> R,
+): ReadOnlyProperty<Any?, R> = ReadOnlyProperty<Any?, R> { thisRef, property ->
+    this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
+}
+
+/**
+ * A converter with a custom reader transformation
+ */
+public fun <R> ItemDelegate.convert(
+    reader: (MetaItem<*>?) -> R,
+): ReadOnlyProperty<Any?, R> = ReadOnlyProperty<Any?, R> { thisRef, property ->
+    this@convert.getValue(thisRef, property).let(reader)
+}
+
+/* Read-only delegates for Metas */
 
 /**
  * A property delegate that uses custom key
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
index 189b9e0f..cc08084c 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
@@ -12,103 +12,148 @@ import kotlin.reflect.KProperty
 
 /* Read-write delegates */
 
-open class MutableItemDelegate(
-    override val owner: MutableItemProvider,
-    key: Name? = null,
-    default: MetaItem<*>? = null
-) : ItemDelegate(owner, key, default), ReadWriteProperty<Any?, MetaItem<*>?> {
+public typealias MutableItemDelegate = ReadWriteProperty<Any?, MetaItem<*>?>
+
+public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = object :MutableItemDelegate {
+
+    override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*>? {
+        return getItem(key ?: property.name.asName())
+    }
 
     override fun setValue(thisRef: Any?, property: KProperty<*>, value: MetaItem<*>?) {
         val name = key ?: property.name.asName()
-        owner.setItem(name, value)
+        setItem(name, value)
+    }
+    //MutableItemDelegate(this, key)
+}
+
+/* Mutable converters */
+
+/**
+ * A type converter for a mutable [MetaItem] delegate
+ */
+public fun <R : Any> MutableItemDelegate.convert(
+    converter: MetaConverter<R>,
+): ReadWriteProperty<Any?, R?> = object : ReadWriteProperty<Any?, R?> {
+
+    override fun getValue(thisRef: Any?, property: KProperty<*>): R? =
+        this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R?) {
+        val item = value?.let(converter::objectToMetaItem)
+        this@convert.setValue(thisRef, property, item)
     }
 }
 
-fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate =
-    MutableItemDelegate(this, key)
+public fun <R : Any> MutableItemDelegate.convert(
+    converter: MetaConverter<R>,
+    default: () -> R,
+): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
 
-//Read-write delegates
+    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
+        this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
+        val item = value.let(converter::objectToMetaItem)
+        this@convert.setValue(thisRef, property, item)
+    }
+}
+
+public fun <R> MutableItemDelegate.convert(
+    reader: (MetaItem<*>?) -> R,
+    writer: (R) -> MetaItem<*>?,
+): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
+
+    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
+        this@convert.getValue(thisRef, property).let(reader)
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
+        val item = value?.let(writer)
+        this@convert.setValue(thisRef, property, item)
+    }
+}
+
+/* Read-write delegates */
 
 /**
  * A property delegate that uses custom key
  */
-fun MutableItemProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
+public fun MutableItemProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
     item(key).convert(MetaConverter.value)
 
-fun MutableItemProvider.string(key: Name? = null): ReadWriteProperty<Any?, String?> =
+public fun MutableItemProvider.string(key: Name? = null): ReadWriteProperty<Any?, String?> =
     item(key).convert(MetaConverter.string)
 
-fun MutableItemProvider.boolean(key: Name? = null): ReadWriteProperty<Any?, Boolean?> =
+public fun MutableItemProvider.boolean(key: Name? = null): ReadWriteProperty<Any?, Boolean?> =
     item(key).convert(MetaConverter.boolean)
 
-fun MutableItemProvider.number(key: Name? = null): ReadWriteProperty<Any?, Number?> =
+public fun MutableItemProvider.number(key: Name? = null): ReadWriteProperty<Any?, Number?> =
     item(key).convert(MetaConverter.number)
 
-fun MutableItemProvider.string(default: String, key: Name? = null): ReadWriteProperty<Any?, String> =
+public fun MutableItemProvider.string(default: String, key: Name? = null): ReadWriteProperty<Any?, String> =
     item(key).convert(MetaConverter.string) { default }
 
-fun MutableItemProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty<Any?, Boolean> =
+public fun MutableItemProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty<Any?, Boolean> =
     item(key).convert(MetaConverter.boolean) { default }
 
-fun MutableItemProvider.number(default: Number, key: Name? = null): ReadWriteProperty<Any?, Number> =
+public fun MutableItemProvider.number(default: Number, key: Name? = null): ReadWriteProperty<Any?, Number> =
     item(key).convert(MetaConverter.number) { default }
 
-fun MutableItemProvider.value(key: Name? = null, default: () -> Value): ReadWriteProperty<Any?, Value> =
+public fun MutableItemProvider.value(key: Name? = null, default: () -> Value): ReadWriteProperty<Any?, Value> =
     item(key).convert(MetaConverter.value, default)
 
-fun MutableItemProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty<Any?, String> =
+public fun MutableItemProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty<Any?, String> =
     item(key).convert(MetaConverter.string, default)
 
-fun MutableItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty<Any?, Boolean> =
+public fun MutableItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty<Any?, Boolean> =
     item(key).convert(MetaConverter.boolean, default)
 
-fun MutableItemProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
+public fun MutableItemProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
     item(key).convert(MetaConverter.number, default)
 
-inline fun <reified E : Enum<E>> MutableItemProvider.enum(default: E, key: Name? = null): ReadWriteProperty<Any?, E> =
+public inline fun <reified E : Enum<E>> MutableItemProvider.enum(default: E, key: Name? = null): ReadWriteProperty<Any?, E> =
     item(key).convert(MetaConverter.enum()) { default }
 
-inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
+public inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
     item(key).convert(reader = { it?.let { it.node as M } }, writer = { it?.let { MetaItem.NodeItem(it) } })
 
 
-fun Configurable.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
+public fun Configurable.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
     item(key).convert(MetaConverter.value)
 
-/* Number delegates*/
+/* Number delegates */
 
-fun MutableItemProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> =
+public fun MutableItemProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> =
     item(key).convert(MetaConverter.int)
 
-fun MutableItemProvider.double(key: Name? = null): ReadWriteProperty<Any?, Double?> =
+public fun MutableItemProvider.double(key: Name? = null): ReadWriteProperty<Any?, Double?> =
     item(key).convert(MetaConverter.double)
 
-fun MutableItemProvider.long(key: Name? = null): ReadWriteProperty<Any?, Long?> =
+public fun MutableItemProvider.long(key: Name? = null): ReadWriteProperty<Any?, Long?> =
     item(key).convert(MetaConverter.long)
 
-fun MutableItemProvider.float(key: Name? = null): ReadWriteProperty<Any?, Float?> =
+public fun MutableItemProvider.float(key: Name? = null): ReadWriteProperty<Any?, Float?> =
     item(key).convert(MetaConverter.float)
 
 
 /* Safe number delegates*/
 
-fun MutableItemProvider.int(default: Int, key: Name? = null): ReadWriteProperty<Any?, Int> =
+public fun MutableItemProvider.int(default: Int, key: Name? = null): ReadWriteProperty<Any?, Int> =
     item(key).convert(MetaConverter.int) { default }
 
-fun MutableItemProvider.double(default: Double, key: Name? = null): ReadWriteProperty<Any?, Double> =
+public fun MutableItemProvider.double(default: Double, key: Name? = null): ReadWriteProperty<Any?, Double> =
     item(key).convert(MetaConverter.double) { default }
 
-fun MutableItemProvider.long(default: Long, key: Name? = null): ReadWriteProperty<Any?, Long> =
+public fun MutableItemProvider.long(default: Long, key: Name? = null): ReadWriteProperty<Any?, Long> =
     item(key).convert(MetaConverter.long) { default }
 
-fun MutableItemProvider.float(default: Float, key: Name? = null): ReadWriteProperty<Any?, Float> =
+public fun MutableItemProvider.float(default: Float, key: Name? = null): ReadWriteProperty<Any?, Float> =
     item(key).convert(MetaConverter.float) { default }
 
 
-/*
- * Extra delegates for special cases
- */
-fun MutableItemProvider.stringList(
+/* Extra delegates for special cases */
+
+public fun MutableItemProvider.stringList(
     vararg default: String,
     key: Name? = null
 ): ReadWriteProperty<Any?, List<String>> = item(key).convert(
@@ -116,14 +161,14 @@ fun MutableItemProvider.stringList(
     writer = { it.map { str -> str.asValue() }.asValue().asMetaItem() }
 )
 
-fun MutableItemProvider.stringList(
+public fun MutableItemProvider.stringList(
     key: Name? = null
 ): ReadWriteProperty<Any?, List<String>?> = item(key).convert(
     reader = {  it?.stringList },
     writer = { it?.map { str -> str.asValue() }?.asValue()?.asMetaItem() }
 )
 
-fun MutableItemProvider.numberList(
+public fun MutableItemProvider.numberList(
     vararg default: Number,
     key: Name? = null
 ): ReadWriteProperty<Any?, List<Number>> = item(key).convert(
@@ -131,10 +176,10 @@ fun MutableItemProvider.numberList(
     writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() }
 )
 
-/**
- * A special delegate for double arrays
- */
-fun MutableItemProvider.doubleArray(
+/* A special delegate for double arrays */
+
+
+public fun MutableItemProvider.doubleArray(
     vararg default: Double,
     key: Name? = null
 ): ReadWriteProperty<Any?, DoubleArray> =item(key).convert(
@@ -142,7 +187,7 @@ fun MutableItemProvider.doubleArray(
     writer = { DoubleArrayValue(it).asMetaItem() }
 )
 
-fun <T> MutableItemProvider.listValue(
+public fun <T> MutableItemProvider.listValue(
     key: Name? = null,
     writer: (T) -> Value = { Value.of(it) },
     reader: (Value) -> T
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/propertyConverter.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/propertyConverter.kt
deleted file mode 100644
index ebe55218..00000000
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/propertyConverter.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-package hep.dataforge.meta
-
-import hep.dataforge.meta.transformations.MetaConverter
-import kotlin.properties.ReadOnlyProperty
-import kotlin.properties.ReadWriteProperty
-import kotlin.reflect.KProperty
-
-/**
- * Apply a converter to this delegate creating a delegate with a custom type
- */
-fun <R : Any> ItemDelegate.convert(
-    converter: MetaConverter<R>
-): ReadOnlyProperty<Any?, R?> = object : ReadOnlyProperty<Any?, R?> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R? =
-        this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
-}
-
-/*
- *
- */
-fun <R : Any> ItemDelegate.convert(
-    converter: MetaConverter<R>,
-    default: () -> R
-): ReadOnlyProperty<Any?, R> = object : ReadOnlyProperty<Any?, R> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
-        this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
-}
-
-/**
- * A converter with a custom reader transformation
- */
-fun <R> ItemDelegate.convert(
-    reader: (MetaItem<*>?) -> R
-): ReadOnlyProperty<Any?, R> = object : ReadOnlyProperty<Any?, R> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
-        this@convert.getValue(thisRef, property).let(reader)
-}
-
-/*Mutable converters*/
-
-/**
- * A type converter for a mutable [MetaItem] delegate
- */
-fun <R : Any> MutableItemDelegate.convert(
-    converter: MetaConverter<R>
-): ReadWriteProperty<Any?, R?> = object : ReadWriteProperty<Any?, R?> {
-
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R? =
-        this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
-
-    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R?) {
-        val item = value?.let(converter::objectToMetaItem)
-        this@convert.setValue(thisRef, property, item)
-    }
-}
-
-fun <R : Any> MutableItemDelegate.convert(
-    converter: MetaConverter<R>,
-    default: () -> R
-): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
-
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
-        this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
-
-    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
-        val item = value.let(converter::objectToMetaItem)
-        this@convert.setValue(thisRef, property, item)
-    }
-}
-
-fun <R> MutableItemDelegate.convert(
-    reader: (MetaItem<*>?) -> R,
-    writer: (R) -> MetaItem<*>?
-): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
-
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
-        this@convert.getValue(thisRef, property).let(reader)
-
-    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
-        val item = value?.let(writer)
-        this@convert.setValue(thisRef, property, item)
-    }
-}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index b0b821fc..e3c8a08e 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -18,7 +18,6 @@ pluginManagement {
         id("ru.mipt.npm.publish") version toolsVersion
         kotlin("jvm") version kotlinVersion
         kotlin("js") version kotlinVersion
-
     }
 }
 

From 52a3c8bc6fb23fa951fe13a56d60274d7066acf3 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Mon, 7 Sep 2020 22:43:39 +0300
Subject: [PATCH 17/40] dataforge-meta cleanup

---
 .../kotlin/hep/dataforge/context/Plugin.kt    |  1 -
 .../kotlin/hep/dataforge/context/PluginTag.kt | 11 ++-
 .../kotlin/hep/dataforge/data/dataJVM.kt      |  3 +-
 .../kotlin/hep/dataforge/meta/Meta.kt         | 21 +++--
 .../kotlin/hep/dataforge/meta/MetaBuilder.kt  | 66 +++++++---------
 .../hep/dataforge/meta/MetaSerializer.kt      |  6 +-
 .../hep/dataforge/meta/MutableItemDelegate.kt | 23 +++---
 .../kotlin/hep/dataforge/meta/MutableMeta.kt  | 51 +++++++------
 .../kotlin/hep/dataforge/meta/Scheme.kt       | 57 +++++++-------
 .../hep/dataforge/meta/Specification.kt       | 27 ++++---
 .../kotlin/hep/dataforge/meta/annotations.kt  |  4 +-
 .../meta/{metaMatcher.kt => getIndexed.kt}    | 12 +--
 .../kotlin/hep/dataforge/meta/mapMeta.kt      |  4 +-
 .../hep/dataforge/meta/serializationUtils.kt  | 76 -------------------
 .../kotlin/hep/dataforge/values/Value.kt      | 58 +++++++-------
 .../hep/dataforge/values/ValueSerializer.kt   | 14 ++--
 .../hep/dataforge/values/exoticValues.kt      |  8 +-
 .../hep/dataforge/values/valueExtensions.kt   | 23 +++---
 .../hep/dataforge/meta/SpecificationTest.kt   |  5 +-
 .../hep/dataforge/meta/serialization.kt       |  6 ++
 20 files changed, 206 insertions(+), 270 deletions(-)
 rename dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/{metaMatcher.kt => getIndexed.kt} (62%)
 delete mode 100644 dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt
 create mode 100644 dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/serialization.kt

diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
index 6a937962..bcc331c0 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
@@ -2,7 +2,6 @@ package hep.dataforge.context
 
 import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaRepr
-import hep.dataforge.meta.buildMeta
 import hep.dataforge.names.Name
 import hep.dataforge.names.toName
 import hep.dataforge.provider.Provider
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginTag.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginTag.kt
index f02308fd..1cd39929 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginTag.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginTag.kt
@@ -2,7 +2,6 @@ package hep.dataforge.context
 
 import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaRepr
-import hep.dataforge.meta.buildMeta
 
 /**
  * The tag which contains information about name, group and version of some
@@ -10,7 +9,7 @@ import hep.dataforge.meta.buildMeta
  *
  * @author Alexander Nozik
  */
-data class PluginTag(
+public data class PluginTag(
     val name: String,
     val group: String = "",
     val version: String = ""
@@ -22,7 +21,7 @@ data class PluginTag(
      * @param otherTag
      * @return
      */
-    fun matches(otherTag: PluginTag): Boolean {
+    public fun matches(otherTag: PluginTag): Boolean {
         return matchesName(otherTag) && matchesGroup(otherTag)
     }
 
@@ -42,9 +41,9 @@ data class PluginTag(
         "version" put version
     }
 
-    companion object {
+    public companion object {
 
-        const val DATAFORGE_GROUP = "hep.dataforge"
+        public const val DATAFORGE_GROUP: String = "hep.dataforge"
 
         /**
          * Build new PluginTag from standard string representation
@@ -52,7 +51,7 @@ data class PluginTag(
          * @param tag
          * @return
          */
-        fun fromString(tag: String): PluginTag {
+        public fun fromString(tag: String): PluginTag {
             val sepIndex = tag.indexOf(":")
             return if (sepIndex >= 0) {
                 PluginTag(group = tag.substring(0, sepIndex), name = tag.substring(sepIndex + 1))
diff --git a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
index 34148b4d..ca9b0024 100644
--- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
+++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
@@ -3,7 +3,6 @@ package hep.dataforge.data
 import kotlinx.coroutines.runBlocking
 import kotlin.reflect.KClass
 import kotlin.reflect.full.isSubclassOf
-import kotlin.reflect.full.isSuperclassOf
 
 /**
  * Block the thread and get data content
@@ -14,7 +13,7 @@ public fun <T : Any> Data<T>.get(): T = runBlocking { await() }
  * Check that node is compatible with given type meaning that each element could be cast to the type
  */
 internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
-    this.type.isSubclassOf(type)
+    type.isSubclassOf(this.type)
 
 internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
     this.type.isSubclassOf(type)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
index 8bb5af94..73ebbe66 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
@@ -12,6 +12,7 @@ import kotlinx.serialization.Serializer
 import kotlinx.serialization.descriptors.SerialDescriptor
 import kotlinx.serialization.encoding.Decoder
 import kotlinx.serialization.encoding.Encoder
+import kotlinx.serialization.json.Json
 
 
 /**
@@ -86,7 +87,7 @@ public sealed class MetaItem<out M : Meta> {
 }
 
 public fun Value.asMetaItem(): ValueItem = ValueItem(this)
-public fun <M:Meta> M.asMetaItem(): NodeItem<M> = NodeItem(this)
+public fun <M : Meta> M.asMetaItem(): NodeItem<M> = NodeItem(this)
 
 /**
  * The object that could be represented as [Meta]. Meta provided by [toMeta] method should fully represent object state.
@@ -96,8 +97,12 @@ public interface MetaRepr {
     public fun toMeta(): Meta
 }
 
-public interface ItemProvider{
+public fun interface ItemProvider {
     public fun getItem(name: Name): MetaItem<*>?
+
+    public companion object {
+        public val EMPTY: ItemProvider = ItemProvider { null }
+    }
 }
 
 /**
@@ -107,6 +112,7 @@ public interface ItemProvider{
  *
  *   * Same name siblings are supported via elements with the same [Name] but different queries
  */
+@Serializable(MetaSerializer::class)
 public interface Meta : MetaRepr, ItemProvider {
     /**
      * Top level items of meta tree
@@ -140,7 +146,7 @@ public interface Meta : MetaRepr, ItemProvider {
          */
         public const val VALUE_KEY: String = "@value"
 
-        public val EMPTY: Meta = object: MetaBase() {
+        public val EMPTY: Meta = object : MetaBase() {
             override val items: Map<NameToken, MetaItem<*>> = emptyMap()
         }
     }
@@ -202,7 +208,7 @@ public interface MetaNode<out M : MetaNode<M>> : Meta {
 /**
  * The same as [Meta.get], but with specific node type
  */
-public operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? = if( this == null) {
+public operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? = if (this == null) {
     null
 } else {
     @Suppress("UNCHECKED_CAST", "ReplaceGetOrSet")
@@ -226,7 +232,10 @@ public abstract class MetaBase : Meta {
 
     override fun hashCode(): Int = items.hashCode()
 
-    override fun toString(): String = JSON_PRETTY.encodeToString(MetaSerializer, this)
+    override fun toString(): String = Json {
+        prettyPrint = true
+        useArrayPolymorphism = true
+    }.encodeToString(MetaSerializer, this)
 }
 
 /**
@@ -240,7 +249,7 @@ public abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M>, MetaBase(
  * If the argument is possibly mutable node, it is copied on creation
  */
 public class SealedMeta internal constructor(
-    override val items: Map<NameToken, MetaItem<SealedMeta>>
+    override val items: Map<NameToken, MetaItem<SealedMeta>>,
 ) : AbstractMetaNode<SealedMeta>()
 
 /**
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt
index da1bafad..b6e933f6 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt
@@ -11,113 +11,109 @@ import kotlin.jvm.JvmName
  * DSL builder for meta. Is not intended to store mutable state
  */
 @DFBuilder
-class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
+public class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
     override fun wrapNode(meta: Meta): MetaBuilder = if (meta is MetaBuilder) meta else meta.builder()
     override fun empty(): MetaBuilder = MetaBuilder()
 
-    infix fun String.put(item: MetaItem<*>?) {
+    public infix fun String.put(item: MetaItem<*>?) {
         set(this, item)
     }
 
-    infix fun String.put(value: Value?) {
+    public infix fun String.put(value: Value?) {
         set(this, value)
     }
 
-    infix fun String.put(string: String?) {
+    public infix fun String.put(string: String?) {
         set(this, string?.asValue())
     }
 
-    infix fun String.put(number: Number?) {
+    public infix fun String.put(number: Number?) {
         set(this, number?.asValue())
     }
 
-    infix fun String.put(boolean: Boolean?) {
+    public infix fun String.put(boolean: Boolean?) {
         set(this, boolean?.asValue())
     }
 
-    infix fun String.put(enum: Enum<*>) {
+    public infix fun String.put(enum: Enum<*>) {
         set(this, EnumValue(enum))
     }
 
     @JvmName("putValues")
-    infix fun String.put(iterable: Iterable<Value>) {
+    public infix fun String.put(iterable: Iterable<Value>) {
         set(this, iterable.asValue())
     }
 
     @JvmName("putNumbers")
-    infix fun String.put(iterable: Iterable<Number>) {
+    public infix fun String.put(iterable: Iterable<Number>) {
         set(this, iterable.map { it.asValue() }.asValue())
     }
 
     @JvmName("putStrings")
-    infix fun String.put(iterable: Iterable<String>) {
+    public infix fun String.put(iterable: Iterable<String>) {
         set(this, iterable.map { it.asValue() }.asValue())
     }
 
-    infix fun String.put(array: DoubleArray) {
+    public infix fun String.put(array: DoubleArray) {
         set(this, array.asValue())
     }
 
-    infix fun String.putValue(any: Any?) {
-        set(this, Value.of(any))
-    }
-
-    infix fun String.put(meta: Meta?) {
+    public infix fun String.put(meta: Meta?) {
         this@MetaBuilder[this] = meta
     }
 
-    infix fun String.put(repr: MetaRepr?) {
+    public infix fun String.put(repr: MetaRepr?) {
         set(this, repr?.toMeta())
     }
 
     @JvmName("putMetas")
-    infix fun String.put(value: Iterable<Meta>) {
+    public infix fun String.put(value: Iterable<Meta>) {
         this@MetaBuilder[this] = value.toList()
     }
 
-    infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) {
+    public infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) {
         this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder)
     }
 
-    infix fun Name.put(value: Value?) {
+    public infix fun Name.put(value: Value?) {
         set(this, value)
     }
 
-    infix fun Name.put(string: String?) {
+    public infix fun Name.put(string: String?) {
         set(this, string?.asValue())
     }
 
-    infix fun Name.put(number: Number?) {
+    public infix fun Name.put(number: Number?) {
         set(this, number?.asValue())
     }
 
-    infix fun Name.put(boolean: Boolean?) {
+    public infix fun Name.put(boolean: Boolean?) {
         set(this, boolean?.asValue())
     }
 
-    infix fun Name.put(enum: Enum<*>) {
+    public infix fun Name.put(enum: Enum<*>) {
         set(this, EnumValue(enum))
     }
 
     @JvmName("putValues")
-    infix fun Name.put(iterable: Iterable<Value>) {
+    public infix fun Name.put(iterable: Iterable<Value>) {
         set(this, iterable.asValue())
     }
 
-    infix fun Name.put(meta: Meta?) {
+    public infix fun Name.put(meta: Meta?) {
         this@MetaBuilder[this] = meta
     }
 
-    infix fun Name.put(repr: MetaRepr?) {
+    public infix fun Name.put(repr: MetaRepr?) {
         set(this, repr?.toMeta())
     }
 
     @JvmName("putMetas")
-    infix fun Name.put(value: Iterable<Meta>) {
+    public infix fun Name.put(value: Iterable<Meta>) {
         this@MetaBuilder[this] = value.toList()
     }
 
-    infix fun Name.put(metaBuilder: MetaBuilder.() -> Unit) {
+    public infix fun Name.put(metaBuilder: MetaBuilder.() -> Unit) {
         this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder)
     }
 }
@@ -125,7 +121,7 @@ class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
 /**
  * For safety, builder always copies the initial meta even if it is builder itself
  */
-fun Meta.builder(): MetaBuilder {
+public fun Meta.builder(): MetaBuilder {
     return MetaBuilder().also { builder ->
         items.mapValues { entry ->
             val item = entry.value
@@ -140,16 +136,10 @@ fun Meta.builder(): MetaBuilder {
 /**
  * Create a deep copy of this meta and apply builder to it
  */
-fun Meta.edit(builder: MetaBuilder.() -> Unit): MetaBuilder = builder().apply(builder)
-
-/**
- * Build a [MetaBuilder] using given transformation
- */
-@Deprecated("To be replaced with fake constructor", ReplaceWith("Meta"))
-fun buildMeta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
+public fun Meta.edit(builder: MetaBuilder.() -> Unit): MetaBuilder = builder().apply(builder)
 
 /**
  * Build a [MetaBuilder] using given transformation
  */
 @Suppress("FunctionName")
-fun Meta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
\ No newline at end of file
+public fun Meta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
index d8f82a9b..dba129bc 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
@@ -1,6 +1,7 @@
 package hep.dataforge.meta
 
 import hep.dataforge.names.NameToken
+import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.Serializer
 import kotlinx.serialization.builtins.MapSerializer
@@ -11,12 +12,13 @@ import kotlinx.serialization.json.JsonDecoder
 import kotlinx.serialization.json.JsonEncoder
 import kotlinx.serialization.json.JsonObject
 
-
 /**
  * Serialized for meta
  */
+@OptIn(ExperimentalSerializationApi::class)
 @Serializer(Meta::class)
-object MetaSerializer : KSerializer<Meta> {
+public object MetaSerializer : KSerializer<Meta> {
+
     private val mapSerializer = MapSerializer(
         NameToken.serializer(),
         MetaItem.serializer(MetaSerializer)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
index cc08084c..4d33bea7 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
@@ -14,8 +14,7 @@ import kotlin.reflect.KProperty
 
 public typealias MutableItemDelegate = ReadWriteProperty<Any?, MetaItem<*>?>
 
-public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = object :MutableItemDelegate {
-
+public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = object : MutableItemDelegate {
     override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*>? {
         return getItem(key ?: property.name.asName())
     }
@@ -24,7 +23,6 @@ public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = ob
         val name = key ?: property.name.asName()
         setItem(name, value)
     }
-    //MutableItemDelegate(this, key)
 }
 
 /* Mutable converters */
@@ -111,7 +109,10 @@ public fun MutableItemProvider.boolean(key: Name? = null, default: () -> Boolean
 public fun MutableItemProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
     item(key).convert(MetaConverter.number, default)
 
-public inline fun <reified E : Enum<E>> MutableItemProvider.enum(default: E, key: Name? = null): ReadWriteProperty<Any?, E> =
+public inline fun <reified E : Enum<E>> MutableItemProvider.enum(
+    default: E,
+    key: Name? = null,
+): ReadWriteProperty<Any?, E> =
     item(key).convert(MetaConverter.enum()) { default }
 
 public inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
@@ -155,22 +156,22 @@ public fun MutableItemProvider.float(default: Float, key: Name? = null): ReadWri
 
 public fun MutableItemProvider.stringList(
     vararg default: String,
-    key: Name? = null
+    key: Name? = null,
 ): ReadWriteProperty<Any?, List<String>> = item(key).convert(
     reader = { it?.stringList ?: listOf(*default) },
     writer = { it.map { str -> str.asValue() }.asValue().asMetaItem() }
 )
 
 public fun MutableItemProvider.stringList(
-    key: Name? = null
+    key: Name? = null,
 ): ReadWriteProperty<Any?, List<String>?> = item(key).convert(
-    reader = {  it?.stringList },
+    reader = { it?.stringList },
     writer = { it?.map { str -> str.asValue() }?.asValue()?.asMetaItem() }
 )
 
 public fun MutableItemProvider.numberList(
     vararg default: Number,
-    key: Name? = null
+    key: Name? = null,
 ): ReadWriteProperty<Any?, List<Number>> = item(key).convert(
     reader = { it?.value?.list?.map { value -> value.number } ?: listOf(*default) },
     writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() }
@@ -181,8 +182,8 @@ public fun MutableItemProvider.numberList(
 
 public fun MutableItemProvider.doubleArray(
     vararg default: Double,
-    key: Name? = null
-): ReadWriteProperty<Any?, DoubleArray> =item(key).convert(
+    key: Name? = null,
+): ReadWriteProperty<Any?, DoubleArray> = item(key).convert(
     reader = { it?.value?.doubleArray ?: doubleArrayOf(*default) },
     writer = { DoubleArrayValue(it).asMetaItem() }
 )
@@ -190,5 +191,5 @@ public fun MutableItemProvider.doubleArray(
 public fun <T> MutableItemProvider.listValue(
     key: Name? = null,
     writer: (T) -> Value = { Value.of(it) },
-    reader: (Value) -> T
+    reader: (Value) -> T,
 ): ReadWriteProperty<Any?, List<T>?> = item(key).convert(MetaConverter.valueList(writer, reader))
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
index 64466554..25cf003f 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
@@ -3,11 +3,11 @@ package hep.dataforge.meta
 import hep.dataforge.names.*
 import hep.dataforge.values.Value
 
-interface MutableItemProvider : ItemProvider {
-    fun setItem(name: Name, item: MetaItem<*>?)
+public interface MutableItemProvider : ItemProvider {
+    public fun setItem(name: Name, item: MetaItem<*>?)
 }
 
-interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider {
+public interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider {
     override val items: Map<NameToken, MetaItem<M>>
 //    fun onChange(owner: Any? = null, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit)
 //    fun removeListener(owner: Any? = null)
@@ -18,7 +18,7 @@ interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider
  *
  * Changes in Meta are not thread safe.
  */
-abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
+public abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
     protected val _items: MutableMap<NameToken, MetaItem<M>> = LinkedHashMap()
 
     override val items: Map<NameToken, MetaItem<M>>
@@ -74,28 +74,28 @@ abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(),
 
 
 @Suppress("NOTHING_TO_INLINE")
-inline fun MutableMeta<*>.remove(name: Name) = setItem(name, null)
+public inline fun MutableMeta<*>.remove(name: Name): Unit = setItem(name, null)
 
 @Suppress("NOTHING_TO_INLINE")
-inline fun MutableMeta<*>.remove(name: String) = remove(name.toName())
+public inline fun MutableMeta<*>.remove(name: String): Unit = remove(name.toName())
 
-operator fun MutableMeta<*>.set(name: Name, item: MetaItem<*>?) = setItem(name, item)
+public operator fun MutableMeta<*>.set(name: Name, item: MetaItem<*>?): Unit = setItem(name, item)
 
-fun MutableMeta<*>.setValue(name: Name, value: Value) = setItem(name, MetaItem.ValueItem(value))
+public fun MutableMeta<*>.setValue(name: Name, value: Value): Unit = setItem(name, MetaItem.ValueItem(value))
 
-fun MutableMeta<*>.setValue(name: String, value: Value) = set(name.toName(), value)
+public fun MutableMeta<*>.setValue(name: String, value: Value): Unit = set(name.toName(), value)
 
-fun MutableMeta<*>.setItem(name: String, item: MetaItem<*>?) = setItem(name.toName(), item)
+public fun MutableMeta<*>.setItem(name: String, item: MetaItem<*>?): Unit = setItem(name.toName(), item)
 
-fun MutableMeta<*>.setNode(name: Name, node: Meta) =
+public fun MutableMeta<*>.setNode(name: Name, node: Meta): Unit =
     setItem(name, MetaItem.NodeItem(node))
 
-fun MutableMeta<*>.setNode(name: String, node: Meta) = setNode(name.toName(), node)
+public fun MutableMeta<*>.setNode(name: String, node: Meta): Unit = setNode(name.toName(), node)
 
 /**
  * Universal unsafe set method
  */
-operator fun MutableMeta<*>.set(name: Name, value: Any?) {
+public operator fun MutableMeta<*>.set(name: Name, value: Any?) {
     when (value) {
         null -> remove(name)
         is MetaItem<*> -> setItem(name, value)
@@ -105,11 +105,14 @@ operator fun MutableMeta<*>.set(name: Name, value: Any?) {
     }
 }
 
-operator fun MutableMeta<*>.set(name: NameToken, value: Any?) = set(name.asName(), value)
+public operator fun MutableMeta<*>.set(name: NameToken, value: Any?): Unit =
+    set(name.asName(), value)
 
-operator fun MutableMeta<*>.set(key: String, value: Any?) = set(key.toName(), value)
+public operator fun MutableMeta<*>.set(key: String, value: Any?): Unit =
+    set(key.toName(), value)
 
-operator fun MutableMeta<*>.set(key: String, index: String, value: Any?) = set(key.toName().withIndex(index), value)
+public operator fun MutableMeta<*>.set(key: String, index: String, value: Any?): Unit =
+    set(key.toName().withIndex(index), value)
 
 /**
  * Update existing mutable node with another node. The rules are following:
@@ -117,7 +120,7 @@ operator fun MutableMeta<*>.set(key: String, index: String, value: Any?) = set(k
  *  * node updates node and replaces anything but node
  *  * node list updates node list if number of nodes in the list is the same and replaces anything otherwise
  */
-fun <M : MutableMeta<M>> M.update(meta: Meta) {
+public fun <M : MutableMeta<M>> M.update(meta: Meta) {
     meta.items.forEach { entry ->
         when (val value = entry.value) {
             is MetaItem.ValueItem -> setValue(entry.key.asName(), value.value)
@@ -129,7 +132,7 @@ fun <M : MutableMeta<M>> M.update(meta: Meta) {
 
 /* Same name siblings generation */
 
-fun MutableMeta<*>.setIndexedItems(
+public fun MutableMeta<*>.setIndexedItems(
     name: Name,
     items: Iterable<MetaItem<*>>,
     indexFactory: (MetaItem<*>, index: Int) -> String = { _, index -> index.toString() }
@@ -143,7 +146,7 @@ fun MutableMeta<*>.setIndexedItems(
     }
 }
 
-fun MutableMeta<*>.setIndexed(
+public fun MutableMeta<*>.setIndexed(
     name: Name,
     metas: Iterable<Meta>,
     indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }
@@ -151,13 +154,13 @@ fun MutableMeta<*>.setIndexed(
     setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }) { item, index -> indexFactory(item.node!!, index) }
 }
 
-operator fun MutableMeta<*>.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
-operator fun MutableMeta<*>.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)
+public operator fun MutableMeta<*>.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
+public operator fun MutableMeta<*>.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)
 
 /**
  * Append the node with a same-name-sibling, automatically generating numerical index
  */
-fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
+public fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
     require(!name.isEmpty()) { "Name could not be empty for append operation" }
     val newIndex = name.lastOrNull()!!.index
     if (newIndex != null) {
@@ -168,13 +171,13 @@ fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
     }
 }
 
-fun <M : MutableMeta<M>> M.append(name: String, value: Any?) = append(name.toName(), value)
+public fun <M : MutableMeta<M>> M.append(name: String, value: Any?): Unit = append(name.toName(), value)
 
 /**
  * Apply existing node with given [builder] or create a new element with it.
  */
 @DFExperimental
-fun <M : AbstractMutableMeta<M>> M.edit(name: Name, builder: M.() -> Unit) {
+public fun <M : AbstractMutableMeta<M>> M.edit(name: Name, builder: M.() -> Unit) {
     val item = when (val existingItem = get(name)) {
         null -> empty().also { set(name, it) }
         is MetaItem.NodeItem<M> -> existingItem.node
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
index deec949f..4adc696a 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
@@ -8,23 +8,21 @@ import hep.dataforge.names.plus
 /**
  * A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
  */
-open class Scheme() : Configurable, Described, MetaRepr {
-    constructor(config: Config, defaultProvider: (Name) -> MetaItem<*>?) : this() {
-        this.config = config
-        this.defaultProvider = defaultProvider
-    }
+public open class Scheme(
+    config: Config,
+    defaultProvider: ItemProvider,
+) : Configurable, Described, MetaRepr {
 
-    //constructor(config: Config, default: Meta) : this(config, { default[it] })
-    constructor(config: Config) : this(config, { null })
-
-    final override var config: Config = Config()
+    override var config: Config = config
         internal set
 
-    var defaultProvider: (Name) -> MetaItem<*>? = { null }
+    public var defaultProvider: ItemProvider = defaultProvider
         internal set
 
+    public constructor() : this(Config(), ItemProvider { null })
+
     override fun getDefaultItem(name: Name): MetaItem<*>? {
-        return defaultProvider(name) ?: descriptor?.get(name)?.defaultItem()
+        return defaultProvider.getItem(name) ?: descriptor?.get(name)?.defaultItem()
     }
 
     /**
@@ -32,7 +30,7 @@ open class Scheme() : Configurable, Described, MetaRepr {
      * values if default value is unavailable.
      * Values from [defaultProvider] completely replace
      */
-    open val defaultLayer: Meta get() = DefaultLayer(Name.EMPTY)
+    public open val defaultLayer: Meta get() = DefaultLayer(Name.EMPTY)
 
     override fun toMeta(): Laminate = Laminate(config, defaultLayer)
 
@@ -50,38 +48,45 @@ open class Scheme() : Configurable, Described, MetaRepr {
     }
 }
 
-inline operator fun <T : Scheme> T.invoke(block: T.() -> Unit) = apply(block)
+/**
+ * A shortcut to edit a [Scheme] object in-place
+ */
+public inline operator fun <T : Scheme> T.invoke(block: T.() -> Unit): T = apply(block)
 
 /**
  * A specification for simplified generation of wrappers
  */
-open class SchemeSpec<T : Scheme>(val builder: () -> T) :
-    Specification<T> {
-    override fun empty(): T = builder()
+public open class SchemeSpec<T : Scheme>(
+    private val builder: (config: Config, defaultProvider: ItemProvider) -> T,
+) : Specification<T> {
 
-    override fun wrap(config: Config, defaultProvider: (Name) -> MetaItem<*>?): T {
-        return empty().apply {
+    public constructor(emptyBuilder: () -> T) : this({ config: Config, defaultProvider: ItemProvider ->
+        emptyBuilder().apply {
             this.config = config
             this.defaultProvider = defaultProvider
         }
-    }
+    })
+
+    override fun empty(): T = builder(Config(), ItemProvider.EMPTY)
+
+    override fun wrap(config: Config, defaultProvider: ItemProvider): T = builder(config, defaultProvider)
 
     @Suppress("OVERRIDE_BY_INLINE")
-    final override inline operator fun invoke(action: T.() -> Unit) = empty().apply(action)
+    final override inline operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
 }
 
 /**
  * A scheme that uses [Meta] as a default layer
  */
-open class MetaScheme(
-    val meta: Meta,
+public open class MetaScheme(
+    private val meta: Meta,
     override val descriptor: NodeDescriptor? = null,
-    config: Config = Config()
+    config: Config = Config(),
 ) : Scheme(config, meta::get) {
     override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
 }
 
-fun Meta.asScheme() =
-    MetaScheme(this)
+public fun Meta.asScheme(): MetaScheme = MetaScheme(this)
 
-fun <T : Configurable> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit) = spec.wrap(this).apply(block)
\ No newline at end of file
+public fun <T : Configurable> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit): T =
+    spec.wrap(this).apply(block)
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
index 85cf7b96..b505ed8a 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
@@ -1,6 +1,5 @@
 package hep.dataforge.meta
 
-import hep.dataforge.names.Name
 import kotlin.jvm.JvmName
 
 /**
@@ -8,32 +7,32 @@ import kotlin.jvm.JvmName
  * By convention [Scheme] companion should inherit this class
  *
  */
-interface Specification<T : Configurable> {
-    fun empty() = wrap()
+public interface Specification<T : Configurable> {
+    public fun empty(): T = wrap()
 
     /**
      * Wrap generic configuration producing instance of desired type
      */
-    fun wrap(config: Config = Config(), defaultProvider: (Name) -> MetaItem<*>? = { null }): T
+    public fun wrap(config: Config = Config(), defaultProvider: ItemProvider = ItemProvider{ null }): T
 
-    operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
+    public operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
 }
 
 /**
  * Update given configuration using given type as a builder
  */
-fun <T : Configurable> Specification<T>.update(config: Config, action: T.() -> Unit): T = wrap(config).apply(action)
+public fun <T : Configurable> Specification<T>.update(config: Config, action: T.() -> Unit): T = wrap(config).apply(action)
 
 /**
  * Wrap a configuration using static meta as default
  */
-fun <T : Configurable> Specification<T>.wrap(config: Config = Config(), default: Meta = Meta.EMPTY): T =
-    wrap(config) { default[it] }
+public fun <T : Configurable> Specification<T>.wrap(config: Config = Config(), default: Meta = Meta.EMPTY): T =
+    wrap(config, default)
 
 /**
  * Wrap a configuration using static meta as default
  */
-fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
+public fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
     val default = source.seal()
     return wrap(source.asConfig(), default)
 }
@@ -42,26 +41,26 @@ fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
 /**
  * Apply specified configuration to configurable
  */
-fun <T : Configurable, C : Configurable, S : Specification<C>> T.configure(spec: S, action: C.() -> Unit) =
+public fun <T : Configurable, C : Configurable, S : Specification<C>> T.configure(spec: S, action: C.() -> Unit): T =
     apply { spec.update(config, action) }
 
 /**
  * Update configuration using given specification
  */
-fun <C : Configurable, S : Specification<C>> Configurable.update(spec: S, action: C.() -> Unit) =
+public fun <C : Configurable, S : Specification<C>> Configurable.update(spec: S, action: C.() -> Unit): Configurable =
     apply { spec.update(config, action) }
 
 /**
  * Create a style based on given specification
  */
-fun <C : Configurable, S : Specification<C>> S.createStyle(action: C.() -> Unit): Meta =
+public fun <C : Configurable, S : Specification<C>> S.createStyle(action: C.() -> Unit): Meta =
     Config().also { update(it, action) }
 
-fun <T : Configurable> MetaItem<*>.spec(spec: Specification<T>): T? = node?.let {
+public fun <T : Configurable> MetaItem<*>.spec(spec: Specification<T>): T? = node?.let {
     spec.wrap(
         Config(), it
     )
 }
 
 @JvmName("configSpec")
-fun <T : Configurable> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
+public fun <T : Configurable> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt
index 2085bc5d..69ffa8aa 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt
@@ -4,8 +4,8 @@ package hep.dataforge.meta
  * General marker for dataforge builders
  */
 @DslMarker
-annotation class DFBuilder
+public annotation class DFBuilder
 
 @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
 @Retention(AnnotationRetention.BINARY)
-annotation class DFExperimental
\ No newline at end of file
+public annotation class DFExperimental
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/getIndexed.kt
similarity index 62%
rename from dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt
rename to dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/getIndexed.kt
index 0ed3190b..20ce93dc 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/getIndexed.kt
@@ -6,7 +6,7 @@ import hep.dataforge.names.*
  * Get all items matching given name. The index of the last element, if present is used as a [Regex],
  * against which indexes of elements are matched.
  */
-fun Meta.getIndexed(name: Name): Map<String?, MetaItem<*>> {
+public fun Meta.getIndexed(name: Name): Map<String?, MetaItem<*>> {
     val root = when (name.length) {
         0 -> error("Can't use empty name for 'getIndexed'")
         1 -> this
@@ -18,19 +18,19 @@ fun Meta.getIndexed(name: Name): Map<String?, MetaItem<*>> {
         root.items.filter { it.key.body == body }.mapKeys { it.key.index }
     } else {
         val regex = index.toRegex()
-        root.items
-            .filter { it.key.body == body && (regex.matches(it.key.index ?: "")) }
+        root.items.filter { it.key.body == body && (regex.matches(it.key.index ?: "")) }
             .mapKeys { it.key.index }
     }
 }
 
-fun Meta.getIndexed(name: String): Map<String?, MetaItem<*>> = this@getIndexed.getIndexed(name.toName())
+public fun Meta.getIndexed(name: String): Map<String?, MetaItem<*>> = this@getIndexed.getIndexed(name.toName())
 
 /**
  * Get all items matching given name.
  */
 @Suppress("UNCHECKED_CAST")
-fun <M : MetaNode<M>> M.getIndexed(name: Name): Map<String, MetaItem<M>> =
+public fun <M : MetaNode<M>> M.getIndexed(name: Name): Map<String, MetaItem<M>> =
     (this as Meta).getIndexed(name) as Map<String, MetaItem<M>>
 
-fun <M : MetaNode<M>> M.getIndexed(name: String): Map<String, MetaItem<M>> = getIndexed(name.toName())
\ No newline at end of file
+public fun <M : MetaNode<M>> M.getIndexed(name: String): Map<String, MetaItem<M>> =
+    getIndexed(name.toName())
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt
index ed77f7f0..774a736a 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt
@@ -8,7 +8,7 @@ import hep.dataforge.values.Value
 /**
  * Convert meta to map of maps
  */
-fun Meta.toMap(descriptor: NodeDescriptor? = null): Map<String, Any?> {
+public fun Meta.toMap(descriptor: NodeDescriptor? = null): Map<String, Any?> {
     return items.entries.associate { (token, item) ->
         token.toString() to when (item) {
             is MetaItem.NodeItem -> item.node.toMap()
@@ -22,7 +22,7 @@ fun Meta.toMap(descriptor: NodeDescriptor? = null): Map<String, Any?> {
  * All other values will be converted to values.
  */
 @DFExperimental
-fun Map<String, Any?>.toMeta(descriptor: NodeDescriptor? = null): Meta = Meta {
+public fun Map<String, Any?>.toMeta(descriptor: NodeDescriptor? = null): Meta = Meta {
     @Suppress("UNCHECKED_CAST")
     fun toItem(value: Any?): MetaItem<*> = when (value) {
         is MetaItem<*> -> value
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt
deleted file mode 100644
index c3f78fe9..00000000
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-package hep.dataforge.meta
-
-import kotlinx.serialization.InternalSerializationApi
-import kotlinx.serialization.builtins.DoubleArraySerializer
-import kotlinx.serialization.builtins.serializer
-import kotlinx.serialization.descriptors.*
-import kotlinx.serialization.encoding.CompositeDecoder
-import kotlinx.serialization.encoding.CompositeEncoder
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import kotlinx.serialization.json.Json
-
-fun ClassSerialDescriptorBuilder.boolean(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, Boolean.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun ClassSerialDescriptorBuilder.string(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, String.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun ClassSerialDescriptorBuilder.int(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, Int.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun ClassSerialDescriptorBuilder.double(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, Double.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun ClassSerialDescriptorBuilder.float(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, Float.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun ClassSerialDescriptorBuilder.long(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, Long.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun ClassSerialDescriptorBuilder.doubleArray(
-    name: String,
-    isOptional: Boolean = false,
-    vararg annotations: Annotation,
-) =
-    element(name, DoubleArraySerializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-@OptIn(InternalSerializationApi::class)
-inline fun <reified E : Enum<E>> ClassSerialDescriptorBuilder.enum(
-    name: String,
-    isOptional: Boolean = false,
-    vararg annotations: Annotation,
-) {
-    val enumDescriptor = buildSerialDescriptor(serialName, SerialKind.ENUM) {
-        enumValues<E>().forEach {
-            val fqn = "$serialName.${it.name}"
-            val enumMemberDescriptor = buildSerialDescriptor(fqn, StructureKind.OBJECT)
-            element(it.name, enumMemberDescriptor)
-        }
-    }
-    element(name, enumDescriptor, isOptional = isOptional, annotations = annotations.toList())
-}
-
-@DFExperimental
-inline fun <R> Decoder.decodeStructure(
-    desc: SerialDescriptor,
-    crossinline block: CompositeDecoder.() -> R,
-): R {
-    val decoder = beginStructure(desc)
-    val res = decoder.block()
-    decoder.endStructure(desc)
-    return res
-}
-
-@DFExperimental
-inline fun Encoder.encodeStructure(
-    desc: SerialDescriptor,
-    block: CompositeEncoder.() -> Unit,
-) {
-    val encoder = beginStructure(desc)
-    encoder.block()
-    encoder.endStructure(desc)
-}
-
-val JSON_PRETTY = Json { prettyPrint = true; useArrayPolymorphism = true }
-val JSON_PLAIN = Json { prettyPrint = false; useArrayPolymorphism = true }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
index 05c082e9..9a95c86d 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
@@ -10,7 +10,7 @@ import kotlinx.serialization.Serializable
  *
  */
 @Serializable
-enum class ValueType {
+public enum class ValueType {
     NUMBER, STRING, BOOLEAN, NULL
 }
 
@@ -19,44 +19,44 @@ enum class ValueType {
  *
  * Value can represent a list of value objects.
  */
-interface Value {
+@Serializable(ValueSerializer::class)
+public interface Value {
     /**
      * Get raw value of this value
      */
-    val value: Any?
+    public val value: Any?
 
     /**
      * The type of the value
      */
-    val type: ValueType
+    public val type: ValueType
 
     /**
      * get this value represented as Number
      */
-    val number: Number
+    public val number: Number
 
     /**
      * get this value represented as String
      */
-    val string: String
+    public val string: String
 
     /**
      * get this value represented as List
      */
-    val list: List<Value>
-        get() = if (this == Null) emptyList() else listOf(this)
+    public val list: List<Value> get() = if (this == Null) emptyList() else listOf(this)
 
     override fun equals(other: Any?): Boolean
 
     override fun hashCode(): Int
 
-    companion object {
-        const val TYPE = "value"
+    public companion object {
+        public const val TYPE: String = "value"
 
         /**
          * Convert object to value
          */
-        fun of(value: Any?): Value {
+        public fun of(value: Any?): Value {
             return when (value) {
                 null -> Null
                 is Value -> value
@@ -89,7 +89,7 @@ interface Value {
 /**
  * A singleton null value
  */
-object Null : Value {
+public object Null : Value {
     override val value: Any? get() = null
     override val type: ValueType get() = ValueType.NULL
     override val number: Number get() = Double.NaN
@@ -104,7 +104,7 @@ object Null : Value {
 /**
  * Singleton true value
  */
-object True : Value {
+public object True : Value {
     override val value: Any? get() = true
     override val type: ValueType get() = ValueType.BOOLEAN
     override val number: Number get() = 1.0
@@ -119,7 +119,7 @@ object True : Value {
 /**
  * Singleton false value
  */
-object False : Value {
+public object False : Value {
     override val value: Any? get() = false
     override val type: ValueType get() = ValueType.BOOLEAN
     override val number: Number get() = -1.0
@@ -131,7 +131,7 @@ object False : Value {
     override fun hashCode(): Int = -1
 }
 
-class NumberValue(override val number: Number) : Value {
+public class NumberValue(override val number: Number) : Value {
     override val value: Any? get() = number
     override val type: ValueType get() = ValueType.NUMBER
     override val string: String get() = number.toString()
@@ -154,7 +154,7 @@ class NumberValue(override val number: Number) : Value {
     override fun toString(): String = value.toString()
 }
 
-class StringValue(override val string: String) : Value {
+public class StringValue(override val string: String) : Value {
     override val value: Any? get() = string
     override val type: ValueType get() = ValueType.STRING
     override val number: Number get() = string.toDouble()
@@ -168,7 +168,7 @@ class StringValue(override val string: String) : Value {
     override fun toString(): String = "\"${value.toString()}\""
 }
 
-class EnumValue<E : Enum<*>>(override val value: E) : Value {
+public class EnumValue<E : Enum<*>>(override val value: E) : Value {
     override val type: ValueType get() = ValueType.STRING
     override val number: Number get() = value.ordinal
     override val string: String get() = value.name
@@ -182,7 +182,7 @@ class EnumValue<E : Enum<*>>(override val value: E) : Value {
     override fun toString(): String = value.toString()
 }
 
-class ListValue(override val list: List<Value>) : Value {
+public class ListValue(override val list: List<Value>) : Value {
     init {
         require(list.isNotEmpty()) { "Can't create list value from empty list" }
     }
@@ -210,34 +210,34 @@ class ListValue(override val list: List<Value>) : Value {
 
 }
 
-fun Number.asValue(): Value = NumberValue(this)
+public fun Number.asValue(): Value = NumberValue(this)
 
-fun Boolean.asValue(): Value = if (this) True else False
+public fun Boolean.asValue(): Value = if (this) True else False
 
-fun String.asValue(): Value = StringValue(this)
+public fun String.asValue(): Value = StringValue(this)
 
-fun Iterable<Value>.asValue(): Value {
+public fun Iterable<Value>.asValue(): Value {
     val list = toList()
     return if (list.isEmpty()) Null else ListValue(this.toList())
 }
 
-fun IntArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
+public fun IntArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
 
-fun LongArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
+public fun LongArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
 
-fun ShortArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
+public fun ShortArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
 
-fun FloatArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
+public fun FloatArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
 
-fun ByteArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
+public fun ByteArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
 
-fun <E : Enum<E>> E.asValue(): Value = EnumValue(this)
+public fun <E : Enum<E>> E.asValue(): Value = EnumValue(this)
 
 
 /**
  * Create Value from String using closest match conversion
  */
-fun String.parseValue(): Value {
+public fun String.parseValue(): Value {
 
     //Trying to get integer
     if (isEmpty() || this == Null.string) {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
index ad57cb71..f7693646 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
@@ -1,25 +1,25 @@
 package hep.dataforge.values
 
-import hep.dataforge.meta.boolean
-import hep.dataforge.meta.enum
-import hep.dataforge.meta.string
+import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.Serializer
 import kotlinx.serialization.builtins.ListSerializer
 import kotlinx.serialization.descriptors.SerialDescriptor
 import kotlinx.serialization.descriptors.buildClassSerialDescriptor
+import kotlinx.serialization.descriptors.element
 import kotlinx.serialization.encoding.Decoder
 import kotlinx.serialization.encoding.Encoder
 
+@OptIn(ExperimentalSerializationApi::class)
 @Serializer(Value::class)
-object ValueSerializer : KSerializer<Value> {
+public object ValueSerializer : KSerializer<Value> {
     private val listSerializer by lazy { ListSerializer(ValueSerializer) }
 
     override val descriptor: SerialDescriptor =
         buildClassSerialDescriptor("hep.dataforge.values.Value") {
-            boolean("isList")
-            enum<ValueType>("valueType")
-            string("value")
+            element<Boolean>("isList")
+            element<ValueType>("valueType")
+            element<String>("value")
         }
 
     private fun Decoder.decodeValue(): Value {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt
index d0fb86e8..4b04a036 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt
@@ -4,7 +4,7 @@ package hep.dataforge.values
 /**
  * A value built from string which content and type are parsed on-demand
  */
-class LazyParsedValue(override val string: String) : Value {
+public class LazyParsedValue(override val string: String) : Value {
     private val parsedValue by lazy { string.parseValue() }
 
     override val value: Any? get() = parsedValue.value
@@ -18,12 +18,12 @@ class LazyParsedValue(override val string: String) : Value {
     override fun hashCode(): Int  = string.hashCode()
 }
 
-fun String.lazyParseValue(): LazyParsedValue = LazyParsedValue(this)
+public fun String.lazyParseValue(): LazyParsedValue = LazyParsedValue(this)
 
 /**
  * A performance optimized version of list value for doubles
  */
-class DoubleArrayValue(override val value: DoubleArray) : Value {
+public class DoubleArrayValue(override val value: DoubleArray) : Value {
     override val type: ValueType get() = ValueType.NUMBER
     override val number: Double get() = value.first()
     override val string: String get() = value.first().toString()
@@ -46,4 +46,4 @@ class DoubleArrayValue(override val value: DoubleArray) : Value {
     override fun toString(): String = list.joinToString (prefix = "[", postfix = "]")
 }
 
-fun DoubleArray.asValue(): Value = if(isEmpty()) Null else DoubleArrayValue(this)
+public fun DoubleArray.asValue(): Value = if(isEmpty()) Null else DoubleArrayValue(this)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt
index 3767e2fb..07e66ea8 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt
@@ -1,32 +1,33 @@
 package hep.dataforge.values
 
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.MetaBuilder
 
 /**
  * Check if value is null
  */
-fun Value.isNull(): Boolean = this == Null
+public fun Value.isNull(): Boolean = this == Null
 
 /**
  * Check if value is list
  */
-fun Value.isList(): Boolean = this.list.size > 1
+public fun Value.isList(): Boolean = this.list.size > 1
 
-val Value.boolean
+public val Value.boolean
     get() = this == True
             || this.list.firstOrNull() == True
             || (type == ValueType.STRING && string.toBoolean())
 
 
-val Value.int get() = number.toInt()
-val Value.double get() = number.toDouble()
-val Value.float get() = number.toFloat()
-val Value.short get() = number.toShort()
-val Value.long get() = number.toLong()
+public val Value.int: Int get() = number.toInt()
+public val Value.double: Double get() = number.toDouble()
+public val Value.float: Float get() = number.toFloat()
+public val Value.short: Short get() = number.toShort()
+public val Value.long: Long get() = number.toLong()
 
-val Value.stringList: List<String> get() = list.map { it.string }
+public val Value.stringList: List<String> get() = list.map { it.string }
 
-val Value.doubleArray: DoubleArray
+public val Value.doubleArray: DoubleArray
     get() = if (this is DoubleArrayValue) {
         value
     } else {
@@ -34,4 +35,4 @@ val Value.doubleArray: DoubleArray
     }
 
 
-fun Value.toMeta() = Meta { Meta.VALUE_KEY put this }
\ No newline at end of file
+public fun Value.toMeta(): MetaBuilder = Meta { Meta.VALUE_KEY put this }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
index f21c5b2c..e74c7bb3 100644
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
@@ -1,18 +1,17 @@
 package hep.dataforge.meta
 
-import hep.dataforge.names.Name
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
 class SpecificationTest {
-    class TestStyled(config: Config, defaultProvider: (Name) -> MetaItem<*>?) :
+    class TestStyled(config: Config, defaultProvider: ItemProvider) :
         Scheme(config, defaultProvider) {
         var list by numberList(1, 2, 3)
 
         companion object : Specification<TestStyled> {
             override fun wrap(
                 config: Config,
-                defaultProvider: (Name) -> MetaItem<*>?
+                defaultProvider: ItemProvider
             ): TestStyled = TestStyled(config, defaultProvider)
         }
     }
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/serialization.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/serialization.kt
new file mode 100644
index 00000000..ecbf8c7a
--- /dev/null
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/serialization.kt
@@ -0,0 +1,6 @@
+package hep.dataforge.meta
+
+import kotlinx.serialization.json.Json
+
+public val JSON_PRETTY: Json = Json { prettyPrint = true; useArrayPolymorphism = true }
+public val JSON_PLAIN: Json = Json { prettyPrint = false; useArrayPolymorphism = true }
\ No newline at end of file

From 8a8484172c99093f0b45e9efc5101678614d655a Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Tue, 8 Sep 2020 16:04:15 +0300
Subject: [PATCH 18/40] Fix IO after refactoring

---
 .../io/yaml/FrontMatterEnvelopeFormat.kt      |  10 +-
 .../kotlin/hep/dataforge/io/IOFormat.kt       |   2 +-
 .../kotlin/hep/dataforge/io/JsonMetaFormat.kt |   6 +-
 .../hep/dataforge/io/TaggedEnvelopeFormat.kt  |  29 ++---
 .../hep/dataforge/io/TaglessEnvelopeFormat.kt |  24 ++--
 .../hep/dataforge/io/EnvelopeFormatTest.kt    |   8 +-
 .../hep/dataforge/io/MetaSerializerTest.kt    |   8 +-
 .../kotlin/hep/dataforge/io/ioTestUtils.kt    |   4 +-
 .../jvmMain/kotlin/hep/dataforge/io/fileIO.kt |  19 +--
 .../dataforge/io/tcp/EnvelopeServerTest.kt    |   4 +-
 .../kotlin/hep/dataforge/meta/JsonMeta.kt     |   5 +-
 .../kotlin/hep/dataforge/meta/Scheme.kt       |  29 +++--
 .../hep/dataforge/meta/Specification.kt       |   7 --
 .../dataforge/meta/descriptors/Described.kt   |   8 +-
 .../meta/descriptors/DescriptorMeta.kt        |  36 ++++--
 .../meta/descriptors/ItemDescriptor.kt        | 115 +++++++++---------
 .../meta/descriptors/DescriptorTest.kt        |   2 +-
 .../hep/dataforge/meta/serialization.kt       |   6 -
 18 files changed, 165 insertions(+), 157 deletions(-)
 delete mode 100644 dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/serialization.kt

diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
index 76d1b152..0fc1d68a 100644
--- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
+++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
@@ -105,11 +105,13 @@ class FrontMatterEnvelopeFormat(
         override fun readPartial(input: Input): PartialEnvelope =
             default.readPartial(input)
 
-        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
-            default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
+        override fun Output.writeEnvelope(
+            envelope: Envelope,
+            metaFormatFactory: MetaFormatFactory,
+            formatMeta: Meta,
+        ): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
 
-        override fun readObject(input: Input): Envelope =
-            default.readObject(input)
+        override fun readObject(input: Input): Envelope = default.readObject(input)
 
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt
index 281381d6..7fe4c970 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt
@@ -30,7 +30,7 @@ public interface IOFormat<T : Any> : MetaRepr {
     }
 }
 
-public fun <T : Any> Input.readWith(format: IOFormat<T>): T = format.run { readObject(this@readWith) }
+public fun <T : Any> Input.readWith(format: IOFormat<T>): T = format.readObject(this@readWith)
 
 /**
  * Read given binary as object using given format
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
index aba20e9c..2be2fe51 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
@@ -12,7 +12,7 @@ import hep.dataforge.meta.toJson
 import hep.dataforge.meta.toMetaItem
 import kotlinx.io.Input
 import kotlinx.io.Output
-import kotlinx.io.readByteArray
+import kotlinx.io.text.readUtf8String
 import kotlinx.io.text.writeUtf8String
 import kotlinx.serialization.json.Json
 import kotlinx.serialization.json.JsonObject
@@ -24,7 +24,7 @@ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat
 
     override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) {
         val jsonObject = meta.toJson(descriptor)
-        output.writeUtf8String(this.json.encodeToString(JsonObject.serializer(), jsonObject))
+        output.writeUtf8String(json.encodeToString(JsonObject.serializer(), jsonObject))
     }
 
     override fun toMeta(): Meta = Meta {
@@ -32,7 +32,7 @@ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat
     }
 
     override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
-        val str = input.readByteArray().decodeToString()
+        val str = input.readUtf8String()//readByteArray().decodeToString()
         val jsonElement = json.parseToJsonElement(str)
         val item = jsonElement.toMetaItem(descriptor)
         return item.node ?: Meta.EMPTY
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
index 19c58910..909ce756 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
@@ -18,7 +18,7 @@ import kotlinx.io.*
  */
 public class TaggedEnvelopeFormat(
     public val io: IOPlugin,
-    public val version: VERSION = VERSION.DF02
+    public val version: VERSION = VERSION.DF02,
 ) : EnvelopeFormat {
 
 //    private val metaFormat = io.metaFormat(metaFormatKey)
@@ -67,11 +67,7 @@ public class TaggedEnvelopeFormat(
         val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
             ?: error("Meta format with key ${tag.metaFormatKey} not found")
 
-        val meta: Meta = input.limit(tag.metaSize.toInt()).run {
-            metaFormat.run {
-                readObject(input)
-            }
-        }
+        val meta: Meta = metaFormat.readObject(input.limit(tag.metaSize.toInt()))
 
         val data = input.readBinary(tag.dataSize.toInt())
 
@@ -84,11 +80,8 @@ public class TaggedEnvelopeFormat(
         val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
             ?: error("Meta format with key ${tag.metaFormatKey} not found")
 
-        val meta: Meta = input.limit(tag.metaSize.toInt()).run {
-            metaFormat.run {
-                readObject(input)
-            }
-        }
+        val meta: Meta = metaFormat.readObject(input.limit(tag.metaSize.toInt()))
+
 
         return PartialEnvelope(meta, version.tagSize + tag.metaSize, tag.dataSize)
     }
@@ -96,7 +89,7 @@ public class TaggedEnvelopeFormat(
     private data class Tag(
         val metaFormatKey: Short,
         val metaSize: UInt,
-        val dataSize: ULong
+        val dataSize: ULong,
     )
 
     public enum class VERSION(public val tagSize: UInt) {
@@ -165,13 +158,13 @@ public class TaggedEnvelopeFormat(
         override fun readPartial(input: Input): PartialEnvelope =
             default.run { readPartial(input) }
 
-        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
-            default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
-
-        override fun readObject(input: Input): Envelope =
-            default.run { readObject(input) }
-
+        override fun Output.writeEnvelope(
+            envelope: Envelope,
+            metaFormatFactory: MetaFormatFactory,
+            formatMeta: Meta,
+        ): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
 
+        override fun readObject(input: Input): Envelope = default.readObject(input)
     }
 
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
index 593e0a95..e0d76350 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
@@ -20,7 +20,7 @@ import kotlin.collections.set
  */
 public class TaglessEnvelopeFormat(
     public val io: IOPlugin,
-    public val meta: Meta = Meta.EMPTY
+    public val meta: Meta = Meta.EMPTY,
 ) : EnvelopeFormat {
 
     private val metaStart = meta[META_START_PROPERTY].string ?: DEFAULT_META_START
@@ -85,13 +85,9 @@ public class TaglessEnvelopeFormat(
             val metaFormat = properties[META_TYPE_PROPERTY]?.let { io.resolveMetaFormat(it) } ?: JsonMetaFormat
             val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
             meta = if (metaSize != null) {
-                input.limit(metaSize).run {
-                    metaFormat.run { readObject(input) }
-                }
+                metaFormat.readObject(input.limit(metaSize))
             } else {
-                metaFormat.run {
-                    readObject(input)
-                }
+                metaFormat.readObject(input)
             }
         }
 
@@ -150,9 +146,7 @@ public class TaglessEnvelopeFormat(
             val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
             meta = if (metaSize != null) {
                 offset += metaSize.toUInt()
-                input.limit(metaSize).run {
-                    metaFormat.run { readObject(input) }
-                }
+                metaFormat.readObject(input.limit(metaSize))
             } else {
                 error("Can't partially read an envelope with undefined meta size")
             }
@@ -203,11 +197,13 @@ public class TaglessEnvelopeFormat(
         override fun readPartial(input: Input): PartialEnvelope =
             default.run { readPartial(input) }
 
-        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
-            default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
+        override fun Output.writeEnvelope(
+            envelope: Envelope,
+            metaFormatFactory: MetaFormatFactory,
+            formatMeta: Meta,
+        ): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
 
-        override fun readObject(input: Input): Envelope =
-            default.run { readObject(input) }
+        override fun readObject(input: Input): Envelope = default.readObject(input)
 
         override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? {
             return try {
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt
index 0fd09abf..8bcc54cd 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt
@@ -23,9 +23,9 @@ class EnvelopeFormatTest {
     @Test
     fun testTaggedFormat(){
         TaggedEnvelopeFormat.run {
-            val byteArray = this.toByteArray(envelope)
+            val byteArray = writeToByteArray(envelope)
             //println(byteArray.decodeToString())
-            val res = readByteArray(byteArray)
+            val res = readFromByteArray(byteArray)
             assertEquals(envelope.meta,res.meta)
             val double = res.data?.read {
                 readDouble()
@@ -37,9 +37,9 @@ class EnvelopeFormatTest {
     @Test
     fun testTaglessFormat(){
         TaglessEnvelopeFormat.run {
-            val byteArray = toByteArray(envelope)
+            val byteArray = writeToByteArray(envelope)
             //println(byteArray.decodeToString())
-            val res = readByteArray(byteArray)
+            val res = readFromByteArray(byteArray)
             assertEquals(envelope.meta,res.meta)
             val double = res.data?.read {
                 readDouble()
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
index 75496d7b..64fd3d02 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
@@ -1,13 +1,19 @@
 package hep.dataforge.io
 
-import hep.dataforge.meta.*
+import hep.dataforge.meta.Meta
+import hep.dataforge.meta.MetaItem
+import hep.dataforge.meta.MetaSerializer
 import hep.dataforge.names.Name
 import hep.dataforge.names.toName
 import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.cbor.Cbor
+import kotlinx.serialization.json.Json
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
+val JSON_PRETTY: Json = Json { prettyPrint = true; useArrayPolymorphism = true }
+val JSON_PLAIN: Json = Json { prettyPrint = false; useArrayPolymorphism = true }
+
 class MetaSerializerTest {
     val meta = Meta {
         "a" put 22
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt
index d27dc9da..55831f03 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt
@@ -3,5 +3,5 @@ package hep.dataforge.io
 import kotlinx.io.ByteArrayInput
 import kotlinx.io.use
 
-fun <T : Any> IOFormat<T>.toByteArray(obj: T): ByteArray = buildByteArray { writeObject(this, obj) }
-fun <T : Any> IOFormat<T>.readByteArray(array: ByteArray): T = ByteArrayInput(array).use { readObject(it) }
\ No newline at end of file
+fun <T : Any> IOFormat<T>.writeToByteArray(obj: T): ByteArray = buildByteArray { writeObject(this, obj) }
+fun <T : Any> IOFormat<T>.readFromByteArray(array: ByteArray): T = ByteArrayInput(array).use { readObject(it) }
\ No newline at end of file
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
index 19c7a14d..3bf0e762 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
@@ -66,7 +66,11 @@ public inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? {
  * Read file containing meta using given [formatOverride] or file extension to infer meta type.
  * If [path] is a directory search for file starting with `meta` in it
  */
-public fun IOPlugin.readMetaFile(path: Path, formatOverride: MetaFormat? = null, descriptor: NodeDescriptor? = null): Meta {
+public fun IOPlugin.readMetaFile(
+    path: Path,
+    formatOverride: MetaFormat? = null,
+    descriptor: NodeDescriptor? = null,
+): Meta {
     if (!Files.exists(path)) error("Meta file $path does not exist")
 
     val actualPath: Path = if (Files.isDirectory(path)) {
@@ -93,7 +97,7 @@ public fun IOPlugin.writeMetaFile(
     path: Path,
     meta: Meta,
     metaFormat: MetaFormatFactory = JsonMetaFormat,
-    descriptor: NodeDescriptor? = null
+    descriptor: NodeDescriptor? = null,
 ) {
     val actualPath = if (Files.isDirectory(path)) {
         path.resolve("@" + metaFormat.name.toString())
@@ -146,14 +150,15 @@ public val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
 public fun IOPlugin.readEnvelopeFile(
     path: Path,
     readNonEnvelopes: Boolean = false,
-    formatPeeker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat
+    formatPeeker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat,
 ): Envelope? {
     if (!Files.exists(path)) return null
 
     //read two-files directory
     if (Files.isDirectory(path)) {
-        val metaFile = Files.list(path).asSequence()
-            .singleOrNull { it.fileName.toString().startsWith(IOPlugin.META_FILE_NAME) }
+        val metaFile = Files.list(path).asSequence().singleOrNull {
+            it.fileName.toString().startsWith(IOPlugin.META_FILE_NAME)
+        }
 
         val meta = if (metaFile == null) {
             Meta.EMPTY
@@ -196,7 +201,7 @@ public fun IOPlugin.writeEnvelopeFile(
     path: Path,
     envelope: Envelope,
     envelopeFormat: EnvelopeFormat = TaggedEnvelopeFormat,
-    metaFormat: MetaFormatFactory? = null
+    metaFormat: MetaFormatFactory? = null,
 ) {
     path.rewrite {
         with(envelopeFormat) {
@@ -212,7 +217,7 @@ public fun IOPlugin.writeEnvelopeFile(
 fun IOPlugin.writeEnvelopeDirectory(
     path: Path,
     envelope: Envelope,
-    metaFormat: MetaFormatFactory = JsonMetaFormat
+    metaFormat: MetaFormatFactory = JsonMetaFormat,
 ) {
     if (!Files.exists(path)) {
         Files.createDirectories(path)
diff --git a/dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt b/dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt
index 48c108d4..850136d5 100644
--- a/dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt
+++ b/dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt
@@ -4,7 +4,7 @@ import hep.dataforge.context.Global
 import hep.dataforge.io.Envelope
 import hep.dataforge.io.Responder
 import hep.dataforge.io.TaggedEnvelopeFormat
-import hep.dataforge.io.toByteArray
+import hep.dataforge.io.writeToByteArray
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.runBlocking
 import kotlinx.io.writeDouble
@@ -18,7 +18,7 @@ import kotlin.time.ExperimentalTime
 @ExperimentalStdlibApi
 object EchoResponder : Responder {
     override suspend fun respond(request: Envelope): Envelope {
-        val string = TaggedEnvelopeFormat().run { toByteArray(request).decodeToString() }
+        val string = TaggedEnvelopeFormat().run { writeToByteArray(request).decodeToString() }
         println("ECHO:")
         println(string)
         return request
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
index debd05c8..2cabc8f1 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
@@ -4,6 +4,7 @@ package hep.dataforge.meta
 
 import hep.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY
 import hep.dataforge.meta.descriptors.ItemDescriptor
+import hep.dataforge.meta.descriptors.ItemDescriptor.Companion.DEFAULT_INDEX_KEY
 import hep.dataforge.meta.descriptors.NodeDescriptor
 import hep.dataforge.meta.descriptors.ValueDescriptor
 import hep.dataforge.names.NameToken
@@ -75,7 +76,7 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
 
 
     if (indexValue != null) {
-        val indexKey = descriptor?.indexKey ?: NodeDescriptor.DEFAULT_INDEX_KEY
+        val indexKey = descriptor?.indexKey ?: DEFAULT_INDEX_KEY
         elementMap[indexKey] = JsonPrimitive(indexValue)
     }
 
@@ -158,7 +159,7 @@ public class JsonMeta(private val json: JsonObject, private val descriptor: Node
                     )
                     map[key] = MetaItem.ValueItem(listValue)
                 } else value.forEachIndexed { index, jsonElement ->
-                    val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: NodeDescriptor.DEFAULT_INDEX_KEY
+                    val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: DEFAULT_INDEX_KEY
                     val indexValue: String = (jsonElement as? JsonObject)
                         ?.get(indexKey)?.jsonPrimitive?.contentOrNull
                         ?: index.toString() //In case index is non-string, the backward transformation will be broken.
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
index 4adc696a..07709ab0 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
@@ -1,9 +1,12 @@
 package hep.dataforge.meta
 
-import hep.dataforge.meta.descriptors.*
+import hep.dataforge.meta.descriptors.Described
+import hep.dataforge.meta.descriptors.NodeDescriptor
+import hep.dataforge.meta.descriptors.defaultItem
+import hep.dataforge.meta.descriptors.get
 import hep.dataforge.names.Name
 import hep.dataforge.names.NameToken
-import hep.dataforge.names.plus
+import hep.dataforge.names.asName
 
 /**
  * A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
@@ -30,21 +33,21 @@ public open class Scheme(
      * values if default value is unavailable.
      * Values from [defaultProvider] completely replace
      */
-    public open val defaultLayer: Meta get() = DefaultLayer(Name.EMPTY)
+    public open val defaultLayer: Meta get() = DefaultLayer()
 
     override fun toMeta(): Laminate = Laminate(config, defaultLayer)
 
-    private inner class DefaultLayer(val path: Name) : MetaBase() {
-        override val items: Map<NameToken, MetaItem<*>> =
-            (descriptor?.get(path) as? NodeDescriptor)?.items?.entries?.associate { (key, descriptor) ->
+    private inner class DefaultLayer : MetaBase() {
+        override val items: Map<NameToken, MetaItem<*>> = buildMap {
+            descriptor?.items?.forEach { (key, itemDescriptor) ->
                 val token = NameToken(key)
-                val fullName = path + token
-                val item: MetaItem<*> = when (descriptor) {
-                    is ValueDescriptor -> getDefaultItem(fullName) ?: descriptor.defaultItem()
-                    is NodeDescriptor -> MetaItem.NodeItem(DefaultLayer(fullName))
+                val name = token.asName()
+                val item = defaultProvider.getItem(name) ?: itemDescriptor.defaultItem()
+                if (item != null) {
+                    put(token, item)
                 }
-                token to item
-            } ?: emptyMap()
+            }
+        }
     }
 }
 
@@ -82,7 +85,7 @@ public open class MetaScheme(
     private val meta: Meta,
     override val descriptor: NodeDescriptor? = null,
     config: Config = Config(),
-) : Scheme(config, meta::get) {
+) : Scheme(config, meta) {
     override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
 }
 
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
index b505ed8a..7988f0c1 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
@@ -23,12 +23,6 @@ public interface Specification<T : Configurable> {
  */
 public fun <T : Configurable> Specification<T>.update(config: Config, action: T.() -> Unit): T = wrap(config).apply(action)
 
-/**
- * Wrap a configuration using static meta as default
- */
-public fun <T : Configurable> Specification<T>.wrap(config: Config = Config(), default: Meta = Meta.EMPTY): T =
-    wrap(config, default)
-
 /**
  * Wrap a configuration using static meta as default
  */
@@ -37,7 +31,6 @@ public fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
     return wrap(source.asConfig(), default)
 }
 
-
 /**
  * Apply specified configuration to configurable
  */
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/Described.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/Described.kt
index ac8ba74a..4af17dfb 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/Described.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/Described.kt
@@ -3,11 +3,11 @@ package hep.dataforge.meta.descriptors
 /**
  * An object which provides its descriptor
  */
-interface Described {
-    val descriptor: ItemDescriptor?
+public interface Described {
+    public val descriptor: ItemDescriptor?
 
-    companion object {
-        const val DESCRIPTOR_NODE = "@descriptor"
+    public companion object {
+        //public const val DESCRIPTOR_NODE: String = "@descriptor"
     }
 }
 
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/DescriptorMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/DescriptorMeta.kt
index 47c90370..9a5b915d 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/DescriptorMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/DescriptorMeta.kt
@@ -1,32 +1,48 @@
 package hep.dataforge.meta.descriptors
 
 import hep.dataforge.meta.Laminate
+import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaBase
 import hep.dataforge.meta.MetaItem
 import hep.dataforge.names.NameToken
-import hep.dataforge.values.Null
 
 /**
- * A [Meta] that wraps a descriptor node
+ * A [Meta] that is constructed from [NodeDescriptor]
  */
-class DescriptorMeta(val descriptor: NodeDescriptor) : MetaBase() {
+private class DescriptorMeta(val descriptor: NodeDescriptor) : Meta, MetaBase() {
     override val items: Map<NameToken, MetaItem<*>>
-        get() = descriptor.items.entries.associate { entry ->
-            NameToken(entry.key) to entry.value.defaultItem()
+        get() = buildMap {
+            descriptor.items.forEach { (token, descriptorItem) ->
+                val item = descriptorItem.defaultItem()
+                if (item != null) {
+                    put(NameToken(token), item)
+                }
+            }
         }
 }
 
-fun NodeDescriptor.buildDefaultMeta() = Laminate(default, DescriptorMeta(this))
+/**
+ * Generate a laminate representing default item set generated by this descriptor
+ */
+public fun NodeDescriptor.defaultMeta(): Laminate = Laminate(default, DescriptorMeta(this))
 
-fun NodeDescriptor.defaultItem(): MetaItem.NodeItem<*> =
-    MetaItem.NodeItem(buildDefaultMeta())
+/**
+ * Build a default [MetaItem.NodeItem] from this node descriptor
+ */
+internal fun NodeDescriptor.defaultItem(): MetaItem.NodeItem<*> =
+    MetaItem.NodeItem(defaultMeta())
 
-fun ValueDescriptor.defaultItem(): MetaItem.ValueItem = MetaItem.ValueItem(default ?: Null)
+/**
+ * Build a default [MetaItem.ValueItem] from this descriptor
+ */
+internal fun ValueDescriptor.defaultItem(): MetaItem.ValueItem? {
+    return MetaItem.ValueItem(default ?: return null)
+}
 
 /**
  * Build a default [MetaItem] from descriptor.
  */
-fun ItemDescriptor.defaultItem(): MetaItem<*> {
+public fun ItemDescriptor.defaultItem(): MetaItem<*>? {
     return when (this) {
         is ValueDescriptor -> defaultItem()
         is NodeDescriptor -> defaultItem()
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt
index 338e1443..cbb56fa1 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt
@@ -4,29 +4,26 @@ import hep.dataforge.meta.*
 import hep.dataforge.names.*
 import hep.dataforge.values.*
 
+/**
+ * A common parent for [ValueDescriptor] and [NodeDescriptor]. Describes a single [MetaItem] or a group of same-name-siblings.
+ */
 @DFBuilder
-sealed class ItemDescriptor(val config: Config) {
+public sealed class ItemDescriptor(public val config: Config) {
 
     /**
      * True if same name siblings with this name are allowed
-     *
-     * @return
      */
-    var multiple: Boolean by config.boolean(false)
+    public var multiple: Boolean by config.boolean(false)
 
     /**
-     * The item description
-     *
-     * @return
+     * The item description text
      */
-    var info: String? by config.string()
+    public var info: String? by config.string()
 
     /**
      * True if the item is required
-     *
-     * @return
      */
-    abstract var required: Boolean
+    public abstract var required: Boolean
 
 
     /**
@@ -34,29 +31,29 @@ sealed class ItemDescriptor(val config: Config) {
      *
      * @return
      */
-    var attributes by config.node()
-}
+    public var attributes: Config? by config.node()
 
-/**
- * Configure attributes of the descriptor
- */
-fun ItemDescriptor.attributes(block: Config.() -> Unit) {
-    (attributes ?: Config().also { this.attributes = it }).apply(block)
-}
+    /**
+     * An index field by which this node is identified in case of same name siblings construct
+     */
+    public var indexKey: String by config.string(DEFAULT_INDEX_KEY)
 
-/**
- * Set specific attribute in the descriptor
- */
-fun ItemDescriptor.setAttribute(name: Name, value: Any?) {
-    attributes {
-        set(name, value)
+    public companion object{
+        public const val DEFAULT_INDEX_KEY: String = "@index"
     }
 }
 
+/**
+ * Configure attributes of the descriptor, creating an attributes node if needed.
+ */
+public fun ItemDescriptor.attributes(block: Config.() -> Unit) {
+    (attributes ?: Config().also { this.attributes = it }).apply(block)
+}
+
 /**
  * Check if given item suits the descriptor
  */
-fun ItemDescriptor.validateItem(item: MetaItem<*>?): Boolean {
+public fun ItemDescriptor.validateItem(item: MetaItem<*>?): Boolean {
     if (item == null) return !required
     return when (this) {
         is ValueDescriptor -> isAllowedValue(item.value ?: return false)
@@ -73,7 +70,7 @@ fun ItemDescriptor.validateItem(item: MetaItem<*>?): Boolean {
  * @author Alexander Nozik
  */
 @DFBuilder
-class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
+public class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
     init {
         config[IS_NODE_KEY] = true
     }
@@ -90,14 +87,12 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      *
      * @return
      */
-    var default by config.node()
+    public var default: Config? by config.node()
 
     /**
-     * An index field by which this node is identified in case of same name siblings construct
+     * The map of children item descriptors (both nodes and values)
      */
-    var indexKey by config.string(DEFAULT_INDEX_KEY)
-
-    val items: Map<String, ItemDescriptor>
+    public val items: Map<String, ItemDescriptor>
         get() = config.getIndexed(ITEM_KEY).mapValues { (_, item) ->
             val node = item.node ?: error("Node descriptor must be a node")
             if (node[IS_NODE_KEY].boolean == true) {
@@ -111,7 +106,7 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      * The map of children node descriptors
      */
     @Suppress("UNCHECKED_CAST")
-    val nodes: Map<String, NodeDescriptor>
+    public val nodes: Map<String, NodeDescriptor>
         get() = config.getIndexed(ITEM_KEY).entries.filter {
             it.value.node[IS_NODE_KEY].boolean == true
         }.associate { (name, item) ->
@@ -120,9 +115,9 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
         }
 
     /**
-     * The list of value descriptors
+     * The list of children value descriptors
      */
-    val values: Map<String, ValueDescriptor>
+    public val values: Map<String, ValueDescriptor>
         get() = config.getIndexed(ITEM_KEY).entries.filter {
             it.value.node[IS_NODE_KEY].boolean != true
         }.associate { (name, item) ->
@@ -154,39 +149,43 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
         config[token] = descriptor.config
     }
 
-    fun item(name: Name, descriptor: ItemDescriptor) {
+    public fun item(name: Name, descriptor: ItemDescriptor) {
         buildNode(name.cutLast()).newItem(name.lastOrNull().toString(), descriptor)
     }
 
-    fun item(name: String, descriptor: ItemDescriptor) {
+    public fun item(name: String, descriptor: ItemDescriptor) {
         item(name.toName(), descriptor)
     }
 
-    fun node(name: Name, block: NodeDescriptor.() -> Unit) {
+    /**
+     * Create and configure a child node descriptor
+     */
+    public fun node(name: Name, block: NodeDescriptor.() -> Unit) {
         item(name, NodeDescriptor().apply(block))
     }
 
-    fun node(name: String, block: NodeDescriptor.() -> Unit) {
+    public fun node(name: String, block: NodeDescriptor.() -> Unit) {
         node(name.toName(), block)
     }
 
-    fun value(name: Name, block: ValueDescriptor.() -> Unit) {
+    /**
+     * Create and configure child value descriptor
+     */
+    public fun value(name: Name, block: ValueDescriptor.() -> Unit) {
         require(name.length >= 1) { "Name length for value descriptor must be non-empty" }
         item(name, ValueDescriptor().apply(block))
     }
 
-    fun value(name: String, block: ValueDescriptor.() -> Unit) {
+    public fun value(name: String, block: ValueDescriptor.() -> Unit) {
         value(name.toName(), block)
     }
 
-    companion object {
+    public companion object {
 
-        val ITEM_KEY = "item".asName()
-        val IS_NODE_KEY = "@isNode".asName()
+        internal val ITEM_KEY: Name = "item".asName()
+        internal val IS_NODE_KEY: Name = "@isNode".asName()
 
-        const val DEFAULT_INDEX_KEY = "@index"
-
-        inline operator fun invoke(block: NodeDescriptor.() -> Unit) = NodeDescriptor().apply(block)
+        public inline operator fun invoke(block: NodeDescriptor.() -> Unit): NodeDescriptor = NodeDescriptor().apply(block)
 
         //TODO infer descriptor from spec
     }
@@ -195,7 +194,7 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
 /**
  * Get a descriptor item associated with given name or null if item for given name not provided
  */
-operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
+public operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
     if (name.isEmpty()) return this
     return when (this) {
         is ValueDescriptor -> null // empty name already checked
@@ -203,7 +202,7 @@ operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
     }
 }
 
-operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName())
+public operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName())
 
 /**
  * A descriptor for meta value
@@ -213,7 +212,7 @@ operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName
  * @author Alexander Nozik
  */
 @DFBuilder
-class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
+public class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
 
     /**
      * True if the value is required
@@ -227,9 +226,9 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      *
      * @return
      */
-    var default: Value? by config.value()
+    public var default: Value? by config.value()
 
-    fun default(v: Any) {
+    public fun default(v: Any) {
         this.default = Value.of(v)
     }
 
@@ -238,9 +237,9 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      *
      * @return
      */
-    var type: List<ValueType>? by config.listValue { ValueType.valueOf(it.string) }
+    public var type: List<ValueType>? by config.listValue { ValueType.valueOf(it.string) }
 
-    fun type(vararg t: ValueType) {
+    public fun type(vararg t: ValueType) {
         this.type = listOf(*t)
     }
 
@@ -251,7 +250,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      * @param value
      * @return
      */
-    fun isAllowedValue(value: Value): Boolean {
+    public fun isAllowedValue(value: Value): Boolean {
         return (type?.let { it.contains(ValueType.STRING) || it.contains(value.type) } ?: true)
                 && (allowedValues.isEmpty() || allowedValues.contains(value))
     }
@@ -262,7 +261,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      *
      * @return
      */
-    var allowedValues: List<Value> by config.item().convert(
+    public var allowedValues: List<Value> by config.item().convert(
         reader = {
             val value = it.value
             when {
@@ -279,7 +278,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
     /**
      * Allow given list of value and forbid others
      */
-    fun allow(vararg v: Any) {
+    public fun allow(vararg v: Any) {
         this.allowedValues = v.map { Value.of(it) }
     }
 }
@@ -287,7 +286,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
 /**
  * Merge two node descriptors into one using first one as primary
  */
-operator fun NodeDescriptor.plus(other: NodeDescriptor): NodeDescriptor {
+public operator fun NodeDescriptor.plus(other: NodeDescriptor): NodeDescriptor {
     return NodeDescriptor().apply {
         config.update(other.config)
         config.update(this@plus.config)
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/descriptors/DescriptorTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/descriptors/DescriptorTest.kt
index 605cbebd..6d2c3ca5 100644
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/descriptors/DescriptorTest.kt
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/descriptors/DescriptorTest.kt
@@ -36,7 +36,7 @@ class DescriptorTest {
 
     @Test
     fun testDefaultMetaNode(){
-        val meta = descriptor.buildDefaultMeta()
+        val meta = descriptor.defaultMeta()
         assertEquals(false, meta["aNode.otherNode.otherValue"].boolean)
     }
 }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/serialization.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/serialization.kt
deleted file mode 100644
index ecbf8c7a..00000000
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/serialization.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package hep.dataforge.meta
-
-import kotlinx.serialization.json.Json
-
-public val JSON_PRETTY: Json = Json { prettyPrint = true; useArrayPolymorphism = true }
-public val JSON_PLAIN: Json = Json { prettyPrint = false; useArrayPolymorphism = true }
\ No newline at end of file

From 606faa5e1b2add29798516ca4bd5931487127070 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Tue, 8 Sep 2020 21:45:50 +0300
Subject: [PATCH 19/40] Explicit mode

---
 .../io/yaml/FrontMatterEnvelopeFormat.kt      | 10 +--
 .../kotlin/hep/dataforge/io/ioMisc.kt         | 14 ++--
 .../hep/dataforge/output/OutputManager.kt     | 24 +++----
 .../kotlin/hep/dataforge/output/Renderer.kt   |  4 +-
 .../hep/dataforge/output/TextRenderer.kt      | 66 ++++++++++---------
 .../kotlin/hep/dataforge/output/outputJS.kt   |  2 +-
 .../kotlin/hep/dataforge/output/outputJVM.kt  |  3 +-
 .../kotlin/hep/dataforge/tables/ColumnDef.kt  |  2 +-
 .../hep/dataforge/tables/ColumnHeader.kt      | 18 ++---
 .../hep/dataforge/tables/ColumnScheme.kt      | 10 +--
 .../hep/dataforge/tables/ColumnTable.kt       |  2 +-
 .../kotlin/hep/dataforge/tables/ListColumn.kt | 10 +--
 .../dataforge/tables/MutableColumnTable.kt    |  6 +-
 .../hep/dataforge/tables/MutableTable.kt      | 14 ++--
 .../kotlin/hep/dataforge/tables/RowTable.kt   |  6 +-
 .../kotlin/hep/dataforge/tables/Table.kt      | 46 ++++++-------
 .../dataforge/tables/TransformationColumn.kt  | 18 ++---
 .../hep/dataforge/tables/io/TextRows.kt       | 20 +++---
 .../dataforge/tables/io/textTableEnvelope.kt  |  4 +-
 .../hep/dataforge/tables/numericColumns.kt    | 16 ++---
 .../hep/dataforge/workspace/Dependency.kt     | 31 ++++-----
 .../hep/dataforge/workspace/GenericTask.kt    | 12 +---
 .../dataforge/workspace/SimpleWorkspace.kt    |  4 +-
 .../kotlin/hep/dataforge/workspace/Task.kt    | 18 ++---
 .../hep/dataforge/workspace/TaskBuilder.kt    | 35 +++++-----
 .../hep/dataforge/workspace/TaskModel.kt      | 42 ++++++------
 .../hep/dataforge/workspace/Workspace.kt      | 26 ++++----
 .../dataforge/workspace/WorkspaceBuilder.kt   | 32 ++++-----
 .../dataforge/workspace/WorkspacePlugin.kt    | 10 +--
 .../hep/dataforge/workspace/envelopeData.kt   |  4 +-
 30 files changed, 251 insertions(+), 258 deletions(-)

diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
index 0fc1d68a..8c3a3c34 100644
--- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
+++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
@@ -11,9 +11,9 @@ import kotlinx.io.text.readUtf8Line
 import kotlinx.io.text.writeUtf8String
 
 @DFExperimental
-class FrontMatterEnvelopeFormat(
-    val io: IOPlugin,
-    val meta: Meta = Meta.EMPTY,
+public class FrontMatterEnvelopeFormat(
+    private val io: IOPlugin,
+    private val meta: Meta = Meta.EMPTY,
 ) : EnvelopeFormat {
 
     override fun readPartial(input: Input): PartialEnvelope {
@@ -80,8 +80,8 @@ class FrontMatterEnvelopeFormat(
         META_KEY put meta
     }
 
-    companion object : EnvelopeFormatFactory {
-        const val SEPARATOR = "---"
+    public companion object : EnvelopeFormatFactory {
+        public const val SEPARATOR = "---"
 
         private val metaTypeRegex = "---(\\w*)\\s*".toRegex()
 
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt
index edb05bf5..283f7638 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt
@@ -3,26 +3,26 @@ package hep.dataforge.io
 import kotlinx.io.*
 import kotlin.math.min
 
-fun Output.writeRawString(str: String) {
+public fun Output.writeRawString(str: String) {
     str.forEach { writeByte(it.toByte()) }
 }
 
-fun Input.readRawString(size: Int): String {
+public fun Input.readRawString(size: Int): String {
     val array = CharArray(size) { readByte().toChar() }
     return array.concatToString()
 }
 
-inline fun buildByteArray(expectedSize: Int = 16, block: Output.() -> Unit): ByteArray =
+public inline fun buildByteArray(expectedSize: Int = 16, block: Output.() -> Unit): ByteArray =
     ByteArrayOutput(expectedSize).apply(block).toByteArray()
 
 @Suppress("FunctionName")
-inline fun Binary(expectedSize: Int = 16, block: Output.() -> Unit): Binary =
+public inline fun Binary(expectedSize: Int = 16, block: Output.() -> Unit): Binary =
     buildByteArray(expectedSize, block).asBinary()
 
 /**
  * View section of a [Binary] as an independent binary
  */
-class BinaryView(private val source: Binary, private val start: Int, override val size: Int) : Binary {
+public class BinaryView(private val source: Binary, private val start: Int, override val size: Int) : Binary {
 
     init {
         require(start > 0)
@@ -34,6 +34,6 @@ class BinaryView(private val source: Binary, private val start: Int, override va
     }
 }
 
-fun Binary.view(start: Int, size: Int) = BinaryView(this, start, size)
+public fun Binary.view(start: Int, size: Int): BinaryView = BinaryView(this, start, size)
 
-operator fun Binary.get(range: IntRange) = view(range.first, range.last - range.first)
\ No newline at end of file
+public operator fun Binary.get(range: IntRange): BinaryView = view(range.first, range.last - range.first)
\ No newline at end of file
diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt
index a8b1697d..f0c71525 100644
--- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt
+++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt
@@ -11,7 +11,7 @@ import kotlin.reflect.KClass
 /**
  * A manager for outputs
  */
-interface OutputManager {
+public interface OutputManager {
 
     /**
      * Get an output specialized for given type, name and stage.
@@ -19,7 +19,7 @@ interface OutputManager {
      * @param name represents the name inside the node.
      * @param meta configuration for [Renderer] (not for rendered object)
      */
-    operator fun <T : Any> get(
+    public operator fun <T : Any> get(
         type: KClass<out T>,
         name: Name,
         stage: Name = Name.EMPTY,
@@ -30,12 +30,12 @@ interface OutputManager {
 /**
  * Get an output manager for a context
  */
-val Context.output: OutputManager get() = plugins.get() ?: ConsoleOutputManager()
+public val Context.output: OutputManager get() = plugins.get() ?: ConsoleOutputManager()
 
 /**
  * Get an output with given [name], [stage] and reified content type
  */
-inline operator fun <reified T : Any> OutputManager.get(
+public inline operator fun <reified T : Any> OutputManager.get(
     name: Name,
     stage: Name = Name.EMPTY,
     meta: Meta = Meta.EMPTY
@@ -46,14 +46,14 @@ inline operator fun <reified T : Any> OutputManager.get(
 /**
  * Directly render an object using the most suitable renderer
  */
-fun OutputManager.render(obj: Any, name: Name, stage: Name = Name.EMPTY, meta: Meta = Meta.EMPTY) =
+public fun OutputManager.render(obj: Any, name: Name, stage: Name = Name.EMPTY, meta: Meta = Meta.EMPTY): Unit =
     get(obj::class, name, stage).render(obj, meta)
 
 /**
  * System console output.
  * The [CONSOLE_RENDERER] is used when no other [OutputManager] is provided.
  */
-val CONSOLE_RENDERER: Renderer<Any> = object : Renderer<Any> {
+public val CONSOLE_RENDERER: Renderer<Any> = object : Renderer<Any> {
     override fun render(obj: Any, meta: Meta) {
         println(obj)
     }
@@ -62,21 +62,21 @@ val CONSOLE_RENDERER: Renderer<Any> = object : Renderer<Any> {
 
 }
 
-class ConsoleOutputManager : AbstractPlugin(), OutputManager {
+public class ConsoleOutputManager : AbstractPlugin(), OutputManager {
     override val tag: PluginTag get() = ConsoleOutputManager.tag
 
     override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Renderer<T> = CONSOLE_RENDERER
 
-    companion object : PluginFactory<ConsoleOutputManager> {
-        override val tag = PluginTag("output.console", group = DATAFORGE_GROUP)
+    public companion object : PluginFactory<ConsoleOutputManager> {
+        override val tag: PluginTag = PluginTag("output.console", group = DATAFORGE_GROUP)
 
-        override val type = ConsoleOutputManager::class
+        override val type: KClass<ConsoleOutputManager> = ConsoleOutputManager::class
 
-        override fun invoke(meta: Meta, context: Context) = ConsoleOutputManager()
+        override fun invoke(meta: Meta, context: Context): ConsoleOutputManager = ConsoleOutputManager()
     }
 }
 
 /**
  * A dispatcher for output tasks.
  */
-expect val Dispatchers.Output: CoroutineDispatcher
\ No newline at end of file
+public expect val Dispatchers.Output: CoroutineDispatcher
\ No newline at end of file
diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt
index 9f8009d1..6e3bee19 100644
--- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt
+++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt
@@ -10,12 +10,12 @@ import hep.dataforge.meta.Meta
  * based on its configuration and provided meta
  *
  */
-interface Renderer<in T : Any> : ContextAware {
+public interface Renderer<in T : Any> : ContextAware {
     /**
      * Render specific object with configuration.
      *
      * By convention actual render is called in asynchronous mode, so this method should never
      * block execution
      */
-    fun render(obj: T, meta: Meta = Meta.EMPTY)
+    public fun render(obj: T, meta: Meta = Meta.EMPTY)
 }
diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
index cc9d24f3..b70030e4 100644
--- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
+++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
@@ -11,7 +11,41 @@ import kotlinx.io.Output
 import kotlinx.io.text.writeUtf8String
 import kotlin.reflect.KClass
 
-class TextRenderer(override val context: Context, private val output: Output) : Renderer<Any> {
+
+/**
+ * A text or binary renderer based on [Output]
+ */
+@Type(TEXT_RENDERER_TYPE)
+public interface TextFormat {
+    /**
+     * The priority of this renderer compared to other renderers
+     */
+    public val priority: Int
+    /**
+     * The type of the content served by this renderer
+     */
+    public val type: KClass<*>
+
+    public suspend fun Output.render(obj: Any)
+
+    public companion object {
+        public const val TEXT_RENDERER_TYPE: String = "dataforge.textRenderer"
+    }
+}
+
+public object DefaultTextFormat : TextFormat {
+    override val priority: Int = Int.MAX_VALUE
+    override val type: KClass<*> = Any::class
+
+    override suspend fun Output.render(obj: Any) {
+        writeUtf8String(obj.toString() + "\n")
+    }
+}
+
+/**
+ * A text-based renderer
+ */
+public class TextRenderer(override val context: Context, private val output: Output) : Renderer<Any> {
     private val cache = HashMap<KClass<*>, TextFormat>()
 
     /**
@@ -39,34 +73,4 @@ class TextRenderer(override val context: Context, private val output: Output) :
             format.run { output.render(obj) }
         }
     }
-}
-
-/**
- * A text or binary renderer based on [Output]
- */
-@Type(TEXT_RENDERER_TYPE)
-interface TextFormat {
-    /**
-     * The priority of this renderer compared to other renderers
-     */
-    val priority: Int
-    /**
-     * The type of the content served by this renderer
-     */
-    val type: KClass<*>
-
-    suspend fun Output.render(obj: Any)
-
-    companion object {
-        const val TEXT_RENDERER_TYPE = "dataforge.textRenderer"
-    }
-}
-
-object DefaultTextFormat : TextFormat {
-    override val priority: Int = Int.MAX_VALUE
-    override val type: KClass<*> = Any::class
-
-    override suspend fun Output.render(obj: Any) {
-        writeUtf8String(obj.toString() + "\n")
-    }
 }
\ No newline at end of file
diff --git a/dataforge-output/src/jsMain/kotlin/hep/dataforge/output/outputJS.kt b/dataforge-output/src/jsMain/kotlin/hep/dataforge/output/outputJS.kt
index 18a71f07..be973122 100644
--- a/dataforge-output/src/jsMain/kotlin/hep/dataforge/output/outputJS.kt
+++ b/dataforge-output/src/jsMain/kotlin/hep/dataforge/output/outputJS.kt
@@ -4,4 +4,4 @@ import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.Dispatchers
 
 
-actual val Dispatchers.Output: CoroutineDispatcher get() = Dispatchers.Default
\ No newline at end of file
+public actual val Dispatchers.Output: CoroutineDispatcher get() = Default
\ No newline at end of file
diff --git a/dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/outputJVM.kt b/dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/outputJVM.kt
index ea7c416c..24c789fd 100644
--- a/dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/outputJVM.kt
+++ b/dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/outputJVM.kt
@@ -1,5 +1,6 @@
 package hep.dataforge.output
 
+import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.Dispatchers
 
-actual val Dispatchers.Output get() = Dispatchers.IO
\ No newline at end of file
+public actual val Dispatchers.Output: CoroutineDispatcher get() = IO
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt
index 2df51d41..2dd2e85b 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt
@@ -3,7 +3,7 @@ package hep.dataforge.tables
 import hep.dataforge.meta.Meta
 import kotlin.reflect.KClass
 
-data class ColumnDef<out T : Any>(
+public data class ColumnDef<out T : Any>(
     override val name: String,
     override val type: KClass<out T>,
     override val meta: Meta
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt
index 2023d11b..a226de26 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt
@@ -8,25 +8,25 @@ import hep.dataforge.values.Value
 import hep.dataforge.values.ValueType
 import kotlin.reflect.KClass
 
-typealias TableHeader<C> = List<ColumnHeader<C>>
+public typealias TableHeader<C> = List<ColumnHeader<C>>
 
-typealias ValueTableHeader = List<ColumnHeader<Value>>
+public typealias ValueTableHeader = List<ColumnHeader<Value>>
 
-interface ColumnHeader<out T : Any> {
-    val name: String
-    val type: KClass<out T>
-    val meta: Meta
+public interface ColumnHeader<out T : Any> {
+    public val name: String
+    public val type: KClass<out T>
+    public val meta: Meta
 }
 
-data class SimpleColumnHeader<T : Any>(
+public data class SimpleColumnHeader<T : Any>(
     override val name: String,
     override val type: KClass<out T>,
     override val meta: Meta
 ) : ColumnHeader<T>
 
-val ColumnHeader<Value>.valueType: ValueType? get() = meta["valueType"].string?.let { ValueType.valueOf(it) }
+public val ColumnHeader<Value>.valueType: ValueType? get() = meta["valueType"].string?.let { ValueType.valueOf(it) }
 
-val ColumnHeader<Value>.textWidth: Int
+public val ColumnHeader<Value>.textWidth: Int
     get() = meta["columnWidth"].int ?: when (valueType) {
         ValueType.NUMBER -> 8
         ValueType.STRING -> 16
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnScheme.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnScheme.kt
index c71ee53f..17968a82 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnScheme.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnScheme.kt
@@ -6,12 +6,12 @@ import hep.dataforge.meta.enum
 import hep.dataforge.meta.string
 import hep.dataforge.values.ValueType
 
-open class ColumnScheme : Scheme() {
-    var title by string()
+public open class ColumnScheme : Scheme() {
+    public var title: String? by string()
 
-    companion object : SchemeSpec<ColumnScheme>(::ColumnScheme)
+    public companion object : SchemeSpec<ColumnScheme>(::ColumnScheme)
 }
 
-class ValueColumnScheme : ColumnScheme() {
-    var valueType by enum(ValueType.STRING)
+public class ValueColumnScheme : ColumnScheme() {
+    public var valueType: ValueType by enum(ValueType.STRING)
 }
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt
index db80b6fa..e79ebd08 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt
@@ -3,7 +3,7 @@ package hep.dataforge.tables
 /**
  * @param T bottom type for all columns in the table
  */
-class ColumnTable<T : Any>(override val columns: Collection<Column<T>>) : Table<T> {
+public class ColumnTable<T : Any>(override val columns: Collection<Column<T>>) : Table<T> {
     private val rowsNum = columns.first().size
 
     init {
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt
index fc7f03ea..7b0549fa 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt
@@ -3,7 +3,7 @@ package hep.dataforge.tables
 import hep.dataforge.meta.Meta
 import kotlin.reflect.KClass
 
-class ListColumn<T : Any>(
+public class ListColumn<T : Any>(
     override val name: String,
     private val data: List<T?>,
     override val type: KClass<out T>,
@@ -13,14 +13,14 @@ class ListColumn<T : Any>(
 
     override fun get(index: Int): T? = data[index]
 
-    companion object {
-        inline operator fun <reified T : Any> invoke(
+    public companion object {
+        public inline operator fun <reified T : Any> invoke(
             name: String,
             def: ColumnScheme,
             data: List<T?>
         ): ListColumn<T> = ListColumn(name, data, T::class, def.toMeta())
 
-        inline operator fun <reified T : Any> invoke(
+        public inline operator fun <reified T : Any> invoke(
             name: String,
             def: ColumnScheme,
             size: Int,
@@ -29,7 +29,7 @@ class ListColumn<T : Any>(
     }
 }
 
-inline fun <T : Any, reified R : Any> Column<T>.map(meta: Meta = this.meta, noinline block: (T?) -> R): Column<R> {
+public inline fun <T : Any, reified R : Any> Column<T>.map(meta: Meta = this.meta, noinline block: (T?) -> R): Column<R> {
     val data = List(size) { block(get(it)) }
     return ListColumn(name, data, R::class, meta)
 }
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt
index 4b93a13d..eb69d7e7 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt
@@ -3,7 +3,7 @@ package hep.dataforge.tables
 /**
  * Mutable table with a fixed size, but dynamic columns
  */
-class MutableColumnTable<C: Any>(val size: Int) : Table<C> {
+public class MutableColumnTable<C: Any>(public val size: Int) : Table<C> {
     private val _columns = ArrayList<Column<C>>()
 
     override val columns: List<Column<C>> get() = _columns
@@ -16,7 +16,7 @@ class MutableColumnTable<C: Any>(val size: Int) : Table<C> {
     /**
      * Add a fixed column to the end of the table
      */
-    fun add(column: Column<C>) {
+    public fun add(column: Column<C>) {
         require(column.size == this.size) { "Required column size $size, but found ${column.size}" }
         _columns.add(column)
     }
@@ -24,7 +24,7 @@ class MutableColumnTable<C: Any>(val size: Int) : Table<C> {
     /**
      * Insert a column at [index]
      */
-    fun insert(index: Int, column: Column<C>) {
+    public fun insert(index: Int, column: Column<C>) {
         require(column.size == this.size) { "Required column size $size, but found ${column.size}" }
         _columns.add(index, column)
     }
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt
index a59108a6..7a1e0376 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt
@@ -4,37 +4,37 @@ import hep.dataforge.meta.Meta
 import hep.dataforge.values.Value
 import kotlin.reflect.KClass
 
-class MutableTable<C : Any>(
+public class MutableTable<C : Any>(
     override val rows: MutableList<Row<C>>,
     override val header: MutableList<ColumnHeader<C>>
 ) : RowTable<C>(rows, header) {
 
-    fun <R : C> column(name: String, type: KClass<out R>, meta: Meta): ColumnHeader<R> {
+    public fun <R : C> column(name: String, type: KClass<out R>, meta: Meta): ColumnHeader<R> {
         val column = SimpleColumnHeader(name, type, meta)
         header.add(column)
         return column
     }
 
-    inline fun <reified T : C> column(
+    public inline fun <reified T : C> column(
         name: String,
         noinline columnMetaBuilder: ColumnScheme.() -> Unit = {}
     ): ColumnHeader<T> {
         return column(name, T::class, ColumnScheme(columnMetaBuilder).toMeta())
     }
 
-    fun row(map: Map<String, C?>): Row<C> {
+    public fun row(map: Map<String, C?>): Row<C> {
         val row = MapRow(map)
         rows.add(row)
         return row
     }
 
-    fun <T : C> row(vararg pairs: Pair<ColumnHeader<T>, T>): Row<C> =
+    public fun <T : C> row(vararg pairs: Pair<ColumnHeader<T>, T>): Row<C> =
         row(pairs.associate { it.first.name to it.second })
 }
 
-fun MutableTable<Value>.row(vararg pairs: Pair<ColumnHeader<Value>, Any?>): Row<Value> =
+public fun MutableTable<Value>.row(vararg pairs: Pair<ColumnHeader<Value>, Any?>): Row<Value> =
     row(pairs.associate { it.first.name to Value.of(it.second) })
 
-fun <C : Any> Table<C>.edit(block: MutableTable<C>.() -> Unit): Table<C> {
+public fun <C : Any> Table<C>.edit(block: MutableTable<C>.() -> Unit): Table<C> {
     return MutableTable(rows.toMutableList(), header.toMutableList()).apply(block)
 }
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt
index aa3449fb..9ea908cc 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt
@@ -4,7 +4,7 @@ import hep.dataforge.meta.Meta
 import kotlinx.coroutines.flow.toList
 import kotlin.reflect.KClass
 
-inline class MapRow<C : Any>(val values: Map<String, C?>) : Row<C> {
+public inline class MapRow<C : Any>(private val values: Map<String, C?>) : Row<C> {
     override fun getValue(column: String): C? = values[column]
 }
 
@@ -17,10 +17,10 @@ internal class RowTableColumn<C : Any, T : C>(val table: Table<C>, val header: C
     override fun get(index: Int): T? = table.rows[index].getValue(name, type)
 }
 
-open class RowTable<C : Any>(override val rows: List<Row<C>>, override val header: List<ColumnHeader<C>>) : Table<C> {
+public open class RowTable<C : Any>(override val rows: List<Row<C>>, override val header: List<ColumnHeader<C>>) : Table<C> {
     override fun getValue(row: Int, column: String): C? = rows[row].getValue(column)
 
     override val columns: List<Column<C>> get() = header.map { RowTableColumn(this, it) }
 }
 
-suspend fun <C : Any> Rows<C>.collect(): Table<C> = this as? Table<C> ?: RowTable(rowFlow().toList(), header)
\ No newline at end of file
+public suspend fun <C : Any> Rows<C>.collect(): Table<C> = this as? Table<C> ?: RowTable(rowFlow().toList(), header)
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt
index 0197955d..72875a05 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt
@@ -9,57 +9,57 @@ import kotlin.reflect.cast
  * Finite or infinite row set. Rows are produced in a lazy suspendable [Flow].
  * Each row must contain at least all the fields mentioned in [header].
  */
-interface Rows<out T : Any> {
-    val header: TableHeader<T>
-    fun rowFlow(): Flow<Row<T>>
+public interface Rows<out T : Any> {
+    public val header: TableHeader<T>
+    public fun rowFlow(): Flow<Row<T>>
 }
 
-interface Table<out T : Any> : Rows<T> {
-    fun getValue(row: Int, column: String): T?
-    val columns: Collection<Column<T>>
+public interface Table<out T : Any> : Rows<T> {
+    public fun getValue(row: Int, column: String): T?
+    public val columns: Collection<Column<T>>
     override val header: TableHeader<T> get() = columns.toList()
-    val rows: List<Row<T>>
+    public val rows: List<Row<T>>
     override fun rowFlow(): Flow<Row<T>> = rows.asFlow()
 
     /**
      * Apply typed query to this table and return lazy [Flow] of resulting rows. The flow could be empty.
      */
     //fun select(query: Any): Flow<Row> = error("Query of type ${query::class} is not supported by this table")
-    companion object {
-        inline operator fun <T : Any> invoke(block: MutableTable<T>.() -> Unit): Table<T> =
+    public companion object {
+        public inline operator fun <T : Any> invoke(block: MutableTable<T>.() -> Unit): Table<T> =
             MutableTable<T>(arrayListOf(), arrayListOf()).apply(block)
     }
 }
 
-fun <C : Any, T : C> Table<C>.getValue(row: Int, column: String, type: KClass<out T>): T? =
+public fun <C : Any, T : C> Table<C>.getValue(row: Int, column: String, type: KClass<out T>): T? =
     type.cast(getValue(row, column))
 
-operator fun <T : Any> Collection<Column<T>>.get(name: String): Column<T>? = find { it.name == name }
+public operator fun <T : Any> Collection<Column<T>>.get(name: String): Column<T>? = find { it.name == name }
 
-inline operator fun <C : Any, reified T : C> Table<C>.get(row: Int, column: String): T? =
+public inline operator fun <C : Any, reified T : C> Table<C>.get(row: Int, column: String): T? =
     getValue(row, column, T::class)
 
-operator fun <C : Any, T : C> Table<C>.get(row: Int, column: ColumnHeader<T>): T? =
+public operator fun <C : Any, T : C> Table<C>.get(row: Int, column: ColumnHeader<T>): T? =
     getValue(row, column.name, column.type)
 
-interface Column<out T : Any> : ColumnHeader<T> {
-    val size: Int
-    operator fun get(index: Int): T?
+public interface Column<out T : Any> : ColumnHeader<T> {
+    public val size: Int
+    public operator fun get(index: Int): T?
 }
 
-val Column<*>.indices get() = (0 until size)
+public val Column<*>.indices: IntRange get() = (0 until size)
 
-operator fun <T : Any> Column<T>.iterator() = iterator {
+public operator fun <T : Any> Column<T>.iterator(): Iterator<T?> = iterator {
     for (i in indices) {
         yield(get(i))
     }
 }
 
-interface Row<out T : Any> {
-    fun getValue(column: String): T?
+public interface Row<out T : Any> {
+    public fun getValue(column: String): T?
 }
 
-fun <C : Any, T : C> Row<C>.getValue(column: String, type: KClass<out T>): T? = type.cast(getValue(column))
+public fun <C : Any, T : C> Row<C>.getValue(column: String, type: KClass<out T>): T? = type.cast(getValue(column))
 
-inline operator fun <reified T : Any> Row<T>.get(column: String): T? = T::class.cast(getValue(column))
-operator fun <C : Any, T : C> Row<C>.get(column: ColumnHeader<T>): T? = getValue(column.name, column.type)
\ No newline at end of file
+public inline operator fun <reified T : Any> Row<T>.get(column: String): T? = T::class.cast(getValue(column))
+public operator fun <C : Any, T : C> Row<C>.get(column: ColumnHeader<T>): T? = getValue(column.name, column.type)
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt
index 3c4fa2b4..83fdc06b 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt
@@ -6,12 +6,12 @@ import kotlin.reflect.KClass
 /**
  * A virtual column obtained by transforming Given row to a single value
  */
-class TransformationColumn<T : Any, R : Any>(
-    val table: Table<T>,
+public class TransformationColumn<T : Any, R : Any>(
+    public val table: Table<T>,
     override val type: KClass<out R>,
     override val name: String,
     override val meta: Meta,
-    val mapper: (Row<T>) -> R?
+    public val mapper: (Row<T>) -> R?
 ) : Column<R> {
     override val size: Int get() = table.rows.size
 
@@ -23,12 +23,12 @@ class TransformationColumn<T : Any, R : Any>(
  *
  * Calls are not thread safe
  */
-class CachedTransformationColumn<T : Any, R : Any>(
-    val table: Table<T>,
+public class CachedTransformationColumn<T : Any, R : Any>(
+    public val table: Table<T>,
     override val type: KClass<out R>,
     override val name: String,
     override val meta: Meta,
-    val mapper: (Row<T>) -> R?
+    public val mapper: (Row<T>) -> R?
 ) : Column<R> {
     override val size: Int get() = table.rows.size
     private val values: HashMap<Int, R?> = HashMap()
@@ -38,7 +38,7 @@ class CachedTransformationColumn<T : Any, R : Any>(
 /**
  * Create a virtual column from a given column
  */
-inline fun <T : Any, reified R : Any> Table<T>.mapRows(
+public inline fun <T : Any, reified R : Any> Table<T>.mapRows(
     name: String,
     meta: Meta = Meta.EMPTY,
     cache: Boolean = false,
@@ -49,12 +49,12 @@ inline fun <T : Any, reified R : Any> Table<T>.mapRows(
     TransformationColumn(this, R::class, name, meta, mapper)
 }
 
-fun <T : Any> Table<T>.mapRowsToDouble(name: String, meta: Meta = Meta.EMPTY, block: (Row<T>) -> Double): RealColumn {
+public fun <T : Any> Table<T>.mapRowsToDouble(name: String, meta: Meta = Meta.EMPTY, block: (Row<T>) -> Double): RealColumn {
     val data = DoubleArray(rows.size) { block(rows[it]) }
     return RealColumn(name, data, meta)
 }
 
-fun <T : Any> Table<T>.mapRowsToInt(name: String, meta: Meta = Meta.EMPTY, block: (Row<T>) -> Int): IntColumn {
+public fun <T : Any> Table<T>.mapRowsToInt(name: String, meta: Meta = Meta.EMPTY, block: (Row<T>) -> Int): IntColumn {
     val data = IntArray(rows.size) { block(rows[it]) }
     return IntColumn(name, data, meta)
 }
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt
index 293031f8..31f5baaa 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt
@@ -32,12 +32,12 @@ private fun readLine(header: ValueTableHeader, line: String): Row<Value> {
  * Finite or infinite [Rows] created from a fixed width text binary
  */
 @ExperimentalIoApi
-class TextRows(override val header: ValueTableHeader, val binary: Binary) : Rows<Value> {
+public class TextRows(override val header: ValueTableHeader, private val binary: Binary) : Rows<Value> {
 
     /**
      * A flow of indexes of string start offsets ignoring empty strings
      */
-    fun indexFlow(): Flow<Int> = binary.read {
+    public fun indexFlow(): Flow<Int> = binary.read {
         var counter: Int = 0
         flow {
             val string = readUtf8StringUntilDelimiter('\n')
@@ -59,23 +59,23 @@ class TextRows(override val header: ValueTableHeader, val binary: Binary) : Rows
         }
     }
 
-    companion object
+    public companion object
 }
 
 /**
  * Create a row offset index for [TextRows]
  */
 @ExperimentalIoApi
-suspend fun TextRows.buildRowIndex(): List<Int> = indexFlow().toList()
+public suspend fun TextRows.buildRowIndex(): List<Int> = indexFlow().toList()
 
 /**
  * Finite table created from [RandomAccessBinary] with fixed width text table
  */
 @ExperimentalIoApi
-class TextTable(
+public class TextTable(
     override val header: ValueTableHeader,
-    val binary: Binary,
-    val index: List<Int>
+    private val binary: Binary,
+    public val index: List<Int>
 ) : Table<Value> {
 
     override val columns: Collection<Column<Value>> get() = header.map { RowTableColumn(this, it) }
@@ -96,8 +96,8 @@ class TextTable(
         return readAt(offset)[column]
     }
 
-    companion object {
-        suspend operator fun invoke(header: ValueTableHeader, binary: Binary): TextTable {
+    public companion object {
+        public suspend operator fun invoke(header: ValueTableHeader, binary: Binary): TextTable {
             val index = TextRows(header, binary).buildRowIndex()
             return TextTable(header, binary, index)
         }
@@ -131,7 +131,7 @@ private fun Output.writeValue(value: Value, width: Int, left: Boolean = true) {
 /**
  * Write rows without header to the output
  */
-suspend fun Output.writeRows(rows: Rows<Value>) {
+public suspend fun Output.writeRows(rows: Rows<Value>) {
     val widths: List<Int> = rows.header.map {
         it.textWidth
     }
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt
index 10c9b3fc..4deb84e6 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt
@@ -12,7 +12,7 @@ import kotlinx.io.asBinary
 
 
 @ExperimentalIoApi
-suspend fun Table<Value>.wrap(): Envelope = Envelope {
+public suspend fun Table<Value>.wrap(): Envelope = Envelope {
     meta {
         header.forEachIndexed { index, columnHeader ->
             set("column", index.toString(), Meta {
@@ -32,7 +32,7 @@ suspend fun Table<Value>.wrap(): Envelope = Envelope {
 
 @DFExperimental
 @ExperimentalIoApi
-fun TextRows.Companion.readEnvelope(envelope: Envelope): TextRows {
+public fun TextRows.Companion.readEnvelope(envelope: Envelope): TextRows {
     val header = envelope.meta.getIndexed("column")
         .entries.sortedBy { it.key?.toInt() }
         .map { (_, item) ->
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt
index 7f80b082..cc386c35 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt
@@ -4,9 +4,9 @@ import hep.dataforge.meta.Meta
 import kotlin.reflect.KClass
 
 
-class RealColumn(
+public class RealColumn(
     override val name: String,
-    val data: DoubleArray,
+    public val data: DoubleArray,
     override val meta: Meta = Meta.EMPTY
 ) : Column<Double> {
     override val type: KClass<out Double> get() = Double::class
@@ -34,8 +34,8 @@ class RealColumn(
         return result
     }
 
-    companion object {
-        inline operator fun <reified T : Any> invoke(
+    public companion object {
+        public inline operator fun <reified T : Any> invoke(
             name: String,
             data: DoubleArray,
             noinline metaBuilder: ColumnScheme.() -> Unit
@@ -43,9 +43,9 @@ class RealColumn(
     }
 }
 
-class IntColumn(
+public class IntColumn(
     override val name: String,
-    val data: IntArray,
+    public val data: IntArray,
     override val meta: Meta = Meta.EMPTY
 ) : Column<Int> {
     override val type: KClass<out Int> get() = Int::class
@@ -73,8 +73,8 @@ class IntColumn(
         return result
     }
 
-    companion object {
-        inline operator fun <reified T : Any> invoke(
+    public companion object {
+        public inline operator fun <reified T : Any> invoke(
             name: String,
             data: IntArray,
             noinline metaBuilder: ColumnScheme.() -> Unit
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt
index ed5ab7f0..10bf38d6 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt
@@ -4,6 +4,7 @@ import hep.dataforge.data.DataFilter
 import hep.dataforge.data.DataNode
 import hep.dataforge.data.filter
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.MetaBuilder
 import hep.dataforge.meta.MetaRepr
 import hep.dataforge.names.Name
 import hep.dataforge.names.asName
@@ -13,11 +14,11 @@ import hep.dataforge.names.plus
 /**
  * A dependency of the task which allows to lazily create a data tree for single dependency
  */
-sealed class Dependency : MetaRepr {
-    abstract fun apply(workspace: Workspace): DataNode<Any>
+public sealed class Dependency : MetaRepr {
+    public abstract fun apply(workspace: Workspace): DataNode<Any>
 }
 
-class DataDependency(val filter: DataFilter, val placement: Name = Name.EMPTY) : Dependency() {
+public class DataDependency(private val filter: DataFilter, private val placement: Name = Name.EMPTY) : Dependency() {
     override fun apply(workspace: Workspace): DataNode<Any> {
         val result = workspace.data.filter(filter)
         return if (placement.isEmpty()) {
@@ -33,29 +34,29 @@ class DataDependency(val filter: DataFilter, val placement: Name = Name.EMPTY) :
     }
 }
 
-class AllDataDependency(val placement: Name = Name.EMPTY) : Dependency() {
+public class AllDataDependency(private val placement: Name = Name.EMPTY) : Dependency() {
     override fun apply(workspace: Workspace): DataNode<Any> = if (placement.isEmpty()) {
         workspace.data
     } else {
         DataNode.invoke(Any::class) { this[placement] = workspace.data }
     }
 
-    override fun toMeta() = Meta {
+    override fun toMeta(): MetaBuilder = Meta {
         "data" put "@all"
         "to" put placement.toString()
     }
 }
 
-abstract class TaskDependency<out T : Any>(
-    val meta: Meta,
-    val placement: Name = Name.EMPTY
+public abstract class TaskDependency<out T : Any>(
+    public val meta: Meta,
+    public val placement: Name = Name.EMPTY
 ) : Dependency() {
-    abstract fun resolveTask(workspace: Workspace): Task<T>
+    public abstract fun resolveTask(workspace: Workspace): Task<T>
 
     /**
      * A name of the dependency for logging and serialization
      */
-    abstract val name: Name
+    public abstract val name: Name
 
     override fun apply(workspace: Workspace): DataNode<T> {
         val task = resolveTask(workspace)
@@ -75,8 +76,8 @@ abstract class TaskDependency<out T : Any>(
     }
 }
 
-class DirectTaskDependency<T : Any>(
-    val task: Task<T>,
+public class DirectTaskDependency<T : Any>(
+    public val task: Task<T>,
     meta: Meta,
     placement: Name
 ) : TaskDependency<T>(meta, placement) {
@@ -84,12 +85,12 @@ class DirectTaskDependency<T : Any>(
 
     override val name: Name get() = DIRECT_TASK_NAME + task.name
 
-    companion object {
-        val DIRECT_TASK_NAME = "@direct".asName()
+    public companion object {
+        public val DIRECT_TASK_NAME: Name = "@direct".asName()
     }
 }
 
-class WorkspaceTaskDependency(
+public class WorkspaceTaskDependency(
     override val name: Name,
     meta: Meta,
     placement: Name
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/GenericTask.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/GenericTask.kt
index 4e0ca715..d3844096 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/GenericTask.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/GenericTask.kt
@@ -1,8 +1,8 @@
 package hep.dataforge.workspace
 
 import hep.dataforge.data.DataNode
-import hep.dataforge.meta.descriptors.NodeDescriptor
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.descriptors.NodeDescriptor
 import hep.dataforge.meta.get
 import hep.dataforge.meta.node
 import hep.dataforge.names.Name
@@ -11,7 +11,7 @@ import kotlin.reflect.KClass
 //data class TaskEnv(val workspace: Workspace, val model: TaskModel)
 
 
-class GenericTask<R : Any>(
+public class GenericTask<R : Any>(
     override val name: Name,
     override val type: KClass<out R>,
     override val descriptor: NodeDescriptor,
@@ -19,14 +19,6 @@ class GenericTask<R : Any>(
     private val dataTransform: Workspace.() -> TaskModel.(DataNode<Any>) -> DataNode<R>
 ) : Task<R> {
 
-//    private fun gather(workspace: Workspace, model: TaskModel): DataNode<Any> {
-//        return DataNode.invoke(Any::class) {
-//            model.dependencies.forEach { dep ->
-//                update(dep.apply(workspace))
-//            }
-//        }
-//    }
-
     override fun run(workspace: Workspace, model: TaskModel): DataNode<R> {
         //validate model
         validate(model)
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
index 5648a822..4159ea30 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
@@ -11,7 +11,7 @@ import hep.dataforge.names.Name
 /**
  * A simple workspace without caching
  */
-class SimpleWorkspace(
+public class SimpleWorkspace(
     override val context: Context,
     override val data: DataNode<Any>,
     override val targets: Map<String, Meta>,
@@ -22,7 +22,7 @@ class SimpleWorkspace(
         context.resolve<Task<*>>(Task.TYPE) + tasks.toMap()
     }
 
-    companion object {
+    public companion object {
 
     }
 }
\ No newline at end of file
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt
index 7511bda9..fbc8637d 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt
@@ -2,23 +2,23 @@ package hep.dataforge.workspace
 
 import hep.dataforge.context.Named
 import hep.dataforge.data.DataNode
-import hep.dataforge.meta.descriptors.Described
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.descriptors.Described
 import hep.dataforge.provider.Type
 import hep.dataforge.workspace.Task.Companion.TYPE
 import kotlin.reflect.KClass
 
 @Type(TYPE)
-interface Task<out R : Any> : Named, Described {
+public interface Task<out R : Any> : Named, Described {
     /**
      * Terminal task is the one that could not build model lazily
      */
-    val isTerminal: Boolean get() = false
+    public val isTerminal: Boolean get() = false
 
     /**
      * The explicit type of the node returned by the task
      */
-    val type: KClass<out R>
+    public val type: KClass<out R>
 
     /**
      * Build a model for this task
@@ -27,14 +27,14 @@ interface Task<out R : Any> : Named, Described {
      * @param taskConfig
      * @return
      */
-    fun build(workspace: Workspace, taskConfig: Meta): TaskModel
+    public fun build(workspace: Workspace, taskConfig: Meta): TaskModel
 
     /**
      * Check if the model is valid and is acceptable by the task. Throw exception if not.
      *
      * @param model
      */
-    fun validate(model: TaskModel) {
+    public fun validate(model: TaskModel) {
         if(this.name != model.name) error("The task $name could not be run with model from task ${model.name}")
     }
 
@@ -46,9 +46,9 @@ interface Task<out R : Any> : Named, Described {
      * @param model - a model to be executed
      * @return
      */
-    fun run(workspace: Workspace, model: TaskModel): DataNode<R>
+    public fun run(workspace: Workspace, model: TaskModel): DataNode<R>
 
-    companion object {
-        const val TYPE = "task"
+    public companion object {
+        public const val TYPE = "task"
     }
 }
\ No newline at end of file
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt
index 502c669d..4cb48843 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt
@@ -14,11 +14,11 @@ import kotlin.jvm.JvmName
 import kotlin.reflect.KClass
 
 @DFBuilder
-class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
+public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass<out R>) {
     private var modelTransform: TaskModelBuilder.(Meta) -> Unit = { allData() }
 
     //    private val additionalDependencies = HashSet<Dependency>()
-    var descriptor: NodeDescriptor? = null
+    private var descriptor: NodeDescriptor? = null
     private val dataTransforms: MutableList<DataTransformation> = ArrayList()
 
     /**
@@ -43,7 +43,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
 //        additionalDependencies.add(dependency)
 //    }
 
-    fun model(modelTransform: TaskModelBuilder.(Meta) -> Unit) {
+    public fun model(modelTransform: TaskModelBuilder.(Meta) -> Unit) {
         this.modelTransform = modelTransform
     }
 
@@ -51,7 +51,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
      * Add a transformation on untyped data
      */
     @JvmName("rawTransform")
-    fun transform(
+    public fun transform(
         from: String = "",
         to: String = "",
         block: TaskEnv.(DataNode<*>) -> DataNode<R>
@@ -62,7 +62,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
         }
     }
 
-    fun <T : Any> transform(
+    public fun <T : Any> transform(
         inputType: KClass<out T>,
         from: String = "",
         to: String = "",
@@ -75,7 +75,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
         }
     }
 
-    inline fun <reified T : Any> transform(
+    public inline fun <reified T : Any> transform(
         from: String = "",
         to: String = "",
         noinline block: TaskEnv.(DataNode<T>) -> DataNode<R>
@@ -86,7 +86,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * Perform given action on data elements in `from` node in input and put the result to `to` node
      */
-    inline fun <reified T : Any> action(
+    public inline fun <reified T : Any> action(
         from: String = "",
         to: String = "",
         crossinline block: TaskEnv.() -> Action<T, R>
@@ -96,8 +96,8 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
         }
     }
 
-    class TaskEnv(val name: Name, val meta: Meta, val context: Context, val data: DataNode<Any>) {
-        operator fun <T : Any> DirectTaskDependency<T>.invoke(): DataNode<T> = if (placement.isEmpty()) {
+    public class TaskEnv(public val name: Name, public val meta: Meta, public val context: Context, public val data: DataNode<Any>) {
+        public operator fun <T : Any> DirectTaskDependency<T>.invoke(): DataNode<T> = if (placement.isEmpty()) {
             data.cast(task.type)
         } else {
             data[placement].node?.cast(task.type)
@@ -108,7 +108,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * A customized map action with ability to change meta and name
      */
-    inline fun <reified T : Any> mapAction(
+    public inline fun <reified T : Any> mapAction(
         from: String = "",
         to: String = "",
         crossinline block: MapActionBuilder<T, R>.(TaskEnv) -> Unit
@@ -127,7 +127,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * A simple map action without changing meta or name
      */
-    inline fun <reified T : Any> map(
+    public inline fun <reified T : Any> map(
         from: String = "",
         to: String = "",
         crossinline block: suspend TaskEnv.(T) -> R
@@ -148,7 +148,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * Join elements in gathered data by multiple groups
      */
-    inline fun <reified T : Any> reduceByGroup(
+    public inline fun <reified T : Any> reduceByGroup(
         from: String = "",
         to: String = "",
         crossinline block: ReduceGroupBuilder<T, R>.(TaskEnv) -> Unit        //TODO needs KEEP-176
@@ -165,7 +165,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * Join all elemlents in gathered data matching input type
      */
-    inline fun <reified T : Any> reduce(
+    public inline fun <reified T : Any> reduce(
         from: String = "",
         to: String = "",
         crossinline block: suspend TaskEnv.(Map<Name, T>) -> R
@@ -188,7 +188,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * Split each element in gathered data into fixed number of fragments
      */
-    inline fun <reified T : Any> split(
+    public inline fun <reified T : Any> split(
         from: String = "",
         to: String = "",
         crossinline block: SplitBuilder<T, R>.(TaskEnv) -> Unit  //TODO needs KEEP-176
@@ -205,16 +205,11 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * Use DSL to create a descriptor for this task
      */
-    fun description(transform: NodeDescriptor.() -> Unit) {
+    public fun description(transform: NodeDescriptor.() -> Unit) {
         this.descriptor = NodeDescriptor().apply(transform)
     }
 
     internal fun build(): GenericTask<R> {
-//        val actualTransform: TaskModelBuilder.(Meta) -> Unit = {
-//            modelTransform
-//            dependencies.addAll(additionalDependencies)
-//        }
-
         return GenericTask(
             name,
             type,
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt
index acd16b2d..d9a558e0 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt
@@ -21,7 +21,7 @@ import hep.dataforge.workspace.TaskModel.Companion.MODEL_TARGET_KEY
  * @param meta the meta for the task (not for the whole configuration)
  * @param dependencies a list of direct dependencies for this task
  */
-data class TaskModel(
+public data class TaskModel(
     val name: Name,
     val meta: Meta,
     val dependencies: Collection<Dependency>
@@ -45,15 +45,15 @@ data class TaskModel(
         }
     }
 
-    companion object {
-        val MODEL_TARGET_KEY = "@target".asName()
+    public companion object {
+        public val MODEL_TARGET_KEY = "@target".asName()
     }
 }
 
 /**
  * Build input for the task
  */
-fun TaskModel.buildInput(workspace: Workspace): DataTree<Any> {
+public fun TaskModel.buildInput(workspace: Workspace): DataTree<Any> {
     return DataTreeBuilder(Any::class).apply {
         dependencies.forEach { dep ->
             update(dep.apply(workspace))
@@ -61,43 +61,43 @@ fun TaskModel.buildInput(workspace: Workspace): DataTree<Any> {
     }.build()
 }
 
-interface TaskDependencyContainer {
-    val defaultMeta: Meta
-    fun add(dependency: Dependency)
+public interface TaskDependencyContainer {
+    public val defaultMeta: Meta
+    public fun add(dependency: Dependency)
 }
 
 /**
  * Add dependency for a task defined in a workspace and resolved by
  */
-fun TaskDependencyContainer.dependsOn(
+public fun TaskDependencyContainer.dependsOn(
     name: Name,
     placement: Name = Name.EMPTY,
     meta: Meta = defaultMeta
 ): WorkspaceTaskDependency =
     WorkspaceTaskDependency(name, meta, placement).also { add(it) }
 
-fun TaskDependencyContainer.dependsOn(
+public fun TaskDependencyContainer.dependsOn(
     name: String,
     placement: Name = Name.EMPTY,
     meta: Meta = defaultMeta
 ): WorkspaceTaskDependency =
     dependsOn(name.toName(), placement, meta)
 
-fun <T : Any> TaskDependencyContainer.dependsOn(
+public fun <T : Any> TaskDependencyContainer.dependsOn(
     task: Task<T>,
     placement: Name = Name.EMPTY,
     meta: Meta = defaultMeta
 ): DirectTaskDependency<T> =
     DirectTaskDependency(task, meta, placement).also { add(it) }
 
-fun <T : Any> TaskDependencyContainer.dependsOn(
+public fun <T : Any> TaskDependencyContainer.dependsOn(
     task: Task<T>,
     placement: String,
     meta: Meta = defaultMeta
 ): DirectTaskDependency<T> =
     DirectTaskDependency(task, meta, placement.toName()).also { add(it) }
 
-fun <T : Any> TaskDependencyContainer.dependsOn(
+public fun <T : Any> TaskDependencyContainer.dependsOn(
     task: Task<T>,
     placement: Name = Name.EMPTY,
     metaBuilder: MetaBuilder.() -> Unit
@@ -107,13 +107,13 @@ fun <T : Any> TaskDependencyContainer.dependsOn(
 /**
  * Add custom data dependency
  */
-fun TaskDependencyContainer.data(action: DataFilter.() -> Unit): DataDependency =
+public fun TaskDependencyContainer.data(action: DataFilter.() -> Unit): DataDependency =
     DataDependency(DataFilter(action)).also { add(it) }
 
 /**
  * User-friendly way to add data dependency
  */
-fun TaskDependencyContainer.data(pattern: String? = null, from: String? = null, to: String? = null): DataDependency =
+public fun TaskDependencyContainer.data(pattern: String? = null, from: String? = null, to: String? = null): DataDependency =
     data {
         pattern?.let { this.pattern = it }
         from?.let { this.from = it }
@@ -123,17 +123,17 @@ fun TaskDependencyContainer.data(pattern: String? = null, from: String? = null,
 /**
  * Add all data as root node
  */
-fun TaskDependencyContainer.allData(to: Name = Name.EMPTY) = AllDataDependency(to).also { add(it) }
+public fun TaskDependencyContainer.allData(to: Name = Name.EMPTY): AllDataDependency = AllDataDependency(to).also { add(it) }
 
 /**
  * A builder for [TaskModel]
  */
-class TaskModelBuilder(val name: Name, meta: Meta = Meta.EMPTY) : TaskDependencyContainer {
+public class TaskModelBuilder(public val name: Name, meta: Meta = Meta.EMPTY) : TaskDependencyContainer {
     /**
      * Meta for current task. By default uses the whole input meta
      */
-    var meta: MetaBuilder = meta.builder()
-    val dependencies = HashSet<Dependency>()
+    public var meta: MetaBuilder = meta.builder()
+    private val dependencies: HashSet<Dependency> = HashSet<Dependency>()
 
     override val defaultMeta: Meta get() = meta
 
@@ -141,11 +141,11 @@ class TaskModelBuilder(val name: Name, meta: Meta = Meta.EMPTY) : TaskDependency
         dependencies.add(dependency)
     }
 
-    var target: String by this.meta.string(key = MODEL_TARGET_KEY, default = "")
+    public var target: String by this.meta.string(key = MODEL_TARGET_KEY, default = "")
 
 
-    fun build(): TaskModel = TaskModel(name, meta.seal(), dependencies)
+    public fun build(): TaskModel = TaskModel(name, meta.seal(), dependencies)
 }
 
 
-val TaskModel.target get() = meta[MODEL_TARGET_KEY]?.string ?: ""
\ No newline at end of file
+public val TaskModel.target: String get() = meta[MODEL_TARGET_KEY]?.string ?: ""
\ No newline at end of file
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
index ac2b1131..063ac25d 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
@@ -15,21 +15,21 @@ import hep.dataforge.provider.Type
 
 
 @Type(Workspace.TYPE)
-interface Workspace : ContextAware, Provider {
+public interface Workspace : ContextAware, Provider {
     /**
      * The whole data node for current workspace
      */
-    val data: DataNode<Any>
+    public val data: DataNode<Any>
 
     /**
      * All targets associated with the workspace
      */
-    val targets: Map<String, Meta>
+    public val targets: Map<String, Meta>
 
     /**
      * All tasks associated with the workspace
      */
-    val tasks: Map<Name, Task<*>>
+    public val tasks: Map<Name, Task<*>>
 
     override fun provideTop(target: String): Map<Name, Any> {
         return when (target) {
@@ -44,7 +44,7 @@ interface Workspace : ContextAware, Provider {
     /**
      * Invoke a task in the workspace utilizing caching if possible
      */
-    fun <R : Any> run(task: Task<R>, config: Meta): DataNode<R> {
+    public fun <R : Any> run(task: Task<R>, config: Meta): DataNode<R> {
         context.activate(this)
         try {
             val model = task.build(this, config)
@@ -55,27 +55,27 @@ interface Workspace : ContextAware, Provider {
         }
     }
 
-    companion object {
-        const val TYPE = "workspace"
-        operator fun invoke(parent: Context = Global, block: SimpleWorkspaceBuilder.() -> Unit): SimpleWorkspace =
+    public companion object {
+        public const val TYPE: String = "workspace"
+        public operator fun invoke(parent: Context = Global, block: SimpleWorkspaceBuilder.() -> Unit): SimpleWorkspace =
             SimpleWorkspaceBuilder(parent).apply(block).build()
     }
 }
 
-fun Workspace.run(task: Task<*>, target: String): DataNode<Any> {
+public fun Workspace.run(task: Task<*>, target: String): DataNode<Any> {
     val meta = targets[target] ?: error("A target with name $target not found in ${this}")
     return run(task, meta)
 }
 
 
-fun Workspace.run(task: String, target: String) =
+public fun Workspace.run(task: String, target: String): DataNode<Any> =
     tasks[task.toName()]?.let { run(it, target) } ?: error("Task with name $task not found")
 
-fun Workspace.run(task: String, meta: Meta) =
+public fun Workspace.run(task: String, meta: Meta): DataNode<Any> =
     tasks[task.toName()]?.let { run(it, meta) } ?: error("Task with name $task not found")
 
-fun Workspace.run(task: String, block: MetaBuilder.() -> Unit = {}) =
+public fun Workspace.run(task: String, block: MetaBuilder.() -> Unit = {}): DataNode<Any> =
     run(task, Meta(block))
 
-fun <T: Any> Workspace.run(task: Task<T>, metaBuilder: MetaBuilder.() -> Unit = {}): DataNode<T> =
+public fun <T: Any> Workspace.run(task: Task<T>, metaBuilder: MetaBuilder.() -> Unit = {}): DataNode<T> =
     run(task, Meta(metaBuilder))
\ No newline at end of file
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt
index a7da78e0..b7f74079 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt
@@ -12,25 +12,25 @@ import kotlin.jvm.JvmName
 import kotlin.reflect.KClass
 
 @DFBuilder
-interface WorkspaceBuilder {
-    val parentContext: Context
-    var context: Context
-    var data: DataTreeBuilder<Any>
-    var tasks: MutableSet<Task<Any>>
-    var targets: MutableMap<String, Meta>
+public interface WorkspaceBuilder {
+    public val parentContext: Context
+    public var context: Context
+    public var data: DataTreeBuilder<Any>
+    public var tasks: MutableSet<Task<Any>>
+    public var targets: MutableMap<String, Meta>
 
-    fun build(): Workspace
+    public fun build(): Workspace
 }
 
 
 /**
  * Set the context for future workspcace
  */
-fun WorkspaceBuilder.context(name: String = "WORKSPACE", block: ContextBuilder.() -> Unit = {}) {
+public fun WorkspaceBuilder.context(name: String = "WORKSPACE", block: ContextBuilder.() -> Unit = {}) {
     context = ContextBuilder(parentContext, name).apply(block).build()
 }
 
-inline fun <reified T : Any> WorkspaceBuilder.data(
+public inline fun <reified T : Any> WorkspaceBuilder.data(
     name: Name = Name.EMPTY,
     noinline block: DataTreeBuilder<T>.() -> Unit
 ): DataNode<T> {
@@ -45,20 +45,20 @@ inline fun <reified T : Any> WorkspaceBuilder.data(
 }
 
 @JvmName("rawData")
-fun WorkspaceBuilder.data(
+public fun WorkspaceBuilder.data(
     name: Name = Name.EMPTY,
     block: DataTreeBuilder<Any>.() -> Unit
 ): DataNode<Any> = data<Any>(name, block)
 
 
-fun WorkspaceBuilder.target(name: String, block: MetaBuilder.() -> Unit) {
+public fun WorkspaceBuilder.target(name: String, block: MetaBuilder.() -> Unit) {
     targets[name] = Meta(block).seal()
 }
 
 /**
  * Use existing target as a base updating it with the block
  */
-fun WorkspaceBuilder.target(name: String, base: String, block: MetaBuilder.() -> Unit) {
+public fun WorkspaceBuilder.target(name: String, base: String, block: MetaBuilder.() -> Unit) {
     val parentTarget = targets[base] ?: error("Base target with name $base not found")
     targets[name] = parentTarget.builder()
         .apply { "@baseTarget" put base }
@@ -66,19 +66,19 @@ fun WorkspaceBuilder.target(name: String, base: String, block: MetaBuilder.() ->
         .seal()
 }
 
-fun <T : Any> WorkspaceBuilder.task(
+public fun <T : Any> WorkspaceBuilder.task(
     name: String,
     type: KClass<out T>,
     builder: TaskBuilder<T>.() -> Unit
 ): Task<T> = TaskBuilder(name.toName(), type).apply(builder).build().also { tasks.add(it) }
 
-inline fun <reified T : Any> WorkspaceBuilder.task(
+public inline fun <reified T : Any> WorkspaceBuilder.task(
     name: String,
     noinline builder: TaskBuilder<T>.() -> Unit
 ): Task<T> = task(name, T::class, builder)
 
 @JvmName("rawTask")
-fun WorkspaceBuilder.task(
+public fun WorkspaceBuilder.task(
     name: String,
     builder: TaskBuilder<Any>.() -> Unit
 ): Task<Any> = task(name, Any::class, builder)
@@ -86,7 +86,7 @@ fun WorkspaceBuilder.task(
 /**
  * A builder for a simple workspace
  */
-class SimpleWorkspaceBuilder(override val parentContext: Context) : WorkspaceBuilder {
+public class SimpleWorkspaceBuilder(override val parentContext: Context) : WorkspaceBuilder {
     override var context: Context = parentContext
     override var data: DataTreeBuilder<Any> = DataTreeBuilder(Any::class)
     override var tasks: MutableSet<Task<Any>> = HashSet()
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
index a377c023..f608b59d 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
@@ -9,9 +9,9 @@ import kotlin.reflect.KClass
 /**
  * An abstract plugin with some additional boilerplate to effectively work with workspace context
  */
-abstract class WorkspacePlugin : AbstractPlugin() {
+public abstract class WorkspacePlugin : AbstractPlugin() {
     private val _tasks = HashSet<Task<*>>()
-    val tasks: Collection<Task<*>> get() = _tasks
+    public val tasks: Collection<Task<*>> get() = _tasks
 
     override fun provideTop(target: String): Map<Name, Any> {
         return when (target) {
@@ -20,11 +20,11 @@ abstract class WorkspacePlugin : AbstractPlugin() {
         }
     }
 
-    fun task(task: Task<*>){
+    public fun task(task: Task<*>){
         _tasks.add(task)
     }
 
-    fun <T : Any> task(
+    public fun <T : Any> task(
         name: String,
         type: KClass<out T>,
         builder: TaskBuilder<T>.() -> Unit
@@ -32,7 +32,7 @@ abstract class WorkspacePlugin : AbstractPlugin() {
         _tasks.add(it)
     }
 
-    inline fun <reified T : Any> task(
+    public inline fun <reified T : Any> task(
         name: String,
         noinline builder: TaskBuilder<T>.() -> Unit
     ) = task(name, T::class, builder)
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/envelopeData.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/envelopeData.kt
index 248e819c..461409e2 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/envelopeData.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/envelopeData.kt
@@ -8,11 +8,11 @@ import kotlin.reflect.KClass
 /**
  * Convert an [Envelope] to a data via given format. The actual parsing is done lazily.
  */
-fun <T : Any> Envelope.toData(type: KClass<out T>, format: IOFormat<T>): Data<T> = Data(type, meta) {
+public fun <T : Any> Envelope.toData(type: KClass<out T>, format: IOFormat<T>): Data<T> = Data(type, meta) {
     data?.readWith(format) ?: error("Can't convert envelope without data to Data")
 }
 
-suspend fun <T : Any> Data<T>.toEnvelope(format: IOFormat<T>): Envelope {
+public suspend fun <T : Any> Data<T>.toEnvelope(format: IOFormat<T>): Envelope {
     val obj = await()
     val binary = format.toBinary(obj)
     return SimpleEnvelope(meta, binary)

From fed787331d393ecb0f1ac100e7b3a60029d61ce2 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Wed, 9 Sep 2020 10:21:16 +0300
Subject: [PATCH 20/40] Kotlin 1.4.20-dev

---
 settings.gradle.kts | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/settings.gradle.kts b/settings.gradle.kts
index e3c8a08e..b7c5529f 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -3,13 +3,15 @@ pluginManagement {
         mavenLocal()
         jcenter()
         gradlePluginPortal()
+        maven("https://dl.bintray.com/kotlin/kotlin-eap")
+        maven("https://dl.bintray.com/kotlin/kotlin-dev")
         maven("https://dl.bintray.com/mipt-npm/dataforge")
         maven("https://dl.bintray.com/mipt-npm/kscience")
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
 
-    val toolsVersion = "0.6.0-dev-4"
-    val kotlinVersion = "1.4.0"
+    val toolsVersion = "0.6.0-dev-5"
+    val kotlinVersion = "1.4.20-dev-3898-14"
 
     plugins {
         id("ru.mipt.npm.mpp") version toolsVersion

From d170f5d60c62128ee482a3669ecccf750feb3755 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Wed, 9 Sep 2020 10:22:15 +0300
Subject: [PATCH 21/40] Explicit API mode

---
 .../kotlin/hep/dataforge/context/Factory.kt   |  4 +-
 .../kotlin/hep/dataforge/context/Named.kt     | 13 +++---
 .../kotlin/hep/dataforge/context/Plugin.kt    | 24 ++++-------
 .../hep/dataforge/context/PluginManager.kt    | 36 ++++++++--------
 .../kotlin/hep/dataforge/provider/Path.kt     | 26 ++++++------
 .../kotlin/hep/dataforge/provider/Provider.kt | 18 ++++----
 .../kotlin/hep/dataforge/provider/Type.kt     |  2 +-
 .../kotlin/hep/dataforge/data/Action.kt       |  8 ++--
 .../hep/dataforge/data/CoroutineMonitor.kt    | 42 ++++++++++++-------
 .../kotlin/hep/dataforge/data/Data.kt         |  2 +-
 .../meta/transformations/MetaConverter.kt     | 40 +++++++++---------
 .../transformations/MetaTransformation.kt     | 38 ++++++++---------
 .../hep/dataforge/values/valueExtensions.kt   |  2 +-
 .../dataforge/workspace/WorkspacePlugin.kt    |  2 +-
 14 files changed, 126 insertions(+), 131 deletions(-)

diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Factory.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Factory.kt
index b01334e6..b8858a13 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Factory.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Factory.kt
@@ -2,6 +2,6 @@ package hep.dataforge.context
 
 import hep.dataforge.meta.Meta
 
-interface Factory<out T : Any> {
-    operator fun invoke(meta: Meta = Meta.EMPTY, context: Context = Global): T
+public interface Factory<out T : Any> {
+    public operator fun invoke(meta: Meta = Meta.EMPTY, context: Context = Global): T
 }
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Named.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Named.kt
index 9e9db17f..e32946e0 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Named.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Named.kt
@@ -24,16 +24,14 @@ import hep.dataforge.names.isEmpty
  *
  * @author Alexander Nozik
  */
-interface Named {
+public interface Named {
 
     /**
      * The name of this object instance
-     *
-     * @return
      */
-    val name: Name
+    public val name: Name
 
-    companion object {
+    public companion object {
 
         /**
          * Get the name of given object. If object is Named its name is used,
@@ -42,7 +40,7 @@ interface Named {
          * @param obj
          * @return
          */
-        fun nameOf(obj: Any): Name {
+        public fun nameOf(obj: Any): Name {
             return if (obj is Named) {
                 obj.name
             } else {
@@ -56,5 +54,4 @@ interface Named {
  * Check if this object has an empty name and therefore is anonymous.
  * @return
  */
-val Named.isAnonymous: Boolean
-    get() = this.name.isEmpty()
+public val Named.isAnonymous: Boolean get() = this.name.isEmpty()
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
index bcc331c0..b8bc6601 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
@@ -22,21 +22,17 @@ import hep.dataforge.provider.Provider
  *
  * @author Alexander Nozik
  */
-interface Plugin : Named, ContextAware, Provider, MetaRepr {
+public interface Plugin : Named, ContextAware, Provider, MetaRepr {
 
     /**
      * Get tag for this plugin
-     *
-     * @return
      */
-    val tag: PluginTag
+    public val tag: PluginTag
 
-    val meta: Meta
+    public val meta: Meta
 
     /**
      * The name of this plugin ignoring version and group
-     *
-     * @return
      */
     override val name: Name get() = tag.name.toName()
 
@@ -44,25 +40,21 @@ interface Plugin : Named, ContextAware, Provider, MetaRepr {
      * Plugin dependencies which are required to attach this plugin. Plugin
      * dependencies must be initialized and enabled in the Context before this
      * plugin is enabled.
-     *
-     * @return
      */
-    fun dependsOn(): Collection<PluginFactory<*>>
+    public fun dependsOn(): Collection<PluginFactory<*>>
 
     /**
      * Start this plugin and attach registration info to the context. This method
      * should be called only via PluginManager to avoid dependency issues.
-     *
-     * @param context
      */
-    fun attach(context: Context)
+    public fun attach(context: Context)
 
     /**
      * Stop this plugin and remove registration info from context and other
      * plugins. This method should be called only via PluginManager to avoid
      * dependency issues.
      */
-    fun detach()
+    public fun detach()
 
     override fun toMeta(): Meta = Meta {
         "context" put context.name.toString()
@@ -71,9 +63,9 @@ interface Plugin : Named, ContextAware, Provider, MetaRepr {
         "meta" put meta
     }
 
-    companion object {
+    public companion object {
 
-        const val PLUGIN_TARGET = "plugin"
+        public const val PLUGIN_TARGET = "plugin"
     }
 
 }
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
index 4f4a062a..dadb333e 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
@@ -5,12 +5,12 @@ import hep.dataforge.meta.MetaBuilder
 import kotlin.reflect.KClass
 
 
-interface PluginFactory<T : Plugin> : Factory<T> {
-    val tag: PluginTag
-    val type: KClass<out T>
+public interface PluginFactory<T : Plugin> : Factory<T> {
+    public val tag: PluginTag
+    public val type: KClass<out T>
 
-    companion object{
-        const val TYPE = "pluginFactory"
+    public companion object{
+        public const val TYPE: String = "pluginFactory"
     }
 }
 
@@ -21,7 +21,7 @@ interface PluginFactory<T : Plugin> : Factory<T> {
  * @property context A context for this plugin manager
  * @author Alexander Nozik
  */
-class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
+public class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
 
     /**
      * A set of loaded plugins
@@ -34,7 +34,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
     private val parent: PluginManager? = context.parent?.plugins
 
 
-    fun sequence(recursive: Boolean): Sequence<Plugin> {
+    public fun sequence(recursive: Boolean): Sequence<Plugin> {
         return if (recursive && parent != null) {
             plugins.asSequence() + parent.sequence(true)
         } else {
@@ -47,7 +47,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
      * @param recursive search for parent [PluginManager] plugins
      * @param predicate condition for the plugin
      */
-    fun find(recursive: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? = sequence(recursive).find(predicate)
+    public fun find(recursive: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? = sequence(recursive).find(predicate)
 
 
     /**
@@ -56,7 +56,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
      * @param tag
      * @return
      */
-    operator fun get(tag: PluginTag, recursive: Boolean = true): Plugin? = find(recursive) { tag.matches(it.tag) }
+    public operator fun get(tag: PluginTag, recursive: Boolean = true): Plugin? = find(recursive) { tag.matches(it.tag) }
 
 
     /**
@@ -71,13 +71,13 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
      * @return
      */
     @Suppress("UNCHECKED_CAST")
-    operator fun <T : Any> get(type: KClass<out T>, tag: PluginTag? = null, recursive: Boolean = true): T? =
+    public operator fun <T : Any> get(type: KClass<out T>, tag: PluginTag? = null, recursive: Boolean = true): T? =
         find(recursive) { type.isInstance(it) && (tag == null || tag.matches(it.tag)) } as T?
 
-    inline operator fun <reified T : Any> get(tag: PluginTag? = null, recursive: Boolean = true): T? =
+    public inline operator fun <reified T : Any> get(tag: PluginTag? = null, recursive: Boolean = true): T? =
         get(T::class, tag, recursive)
 
-    inline operator fun <reified T : Plugin> get(factory: PluginFactory<T>, recursive: Boolean = true): T? =
+    public inline operator fun <reified T : Plugin> get(factory: PluginFactory<T>, recursive: Boolean = true): T? =
         get(factory.type, factory.tag, recursive)
 
     /**
@@ -87,7 +87,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
      * @param plugin
      * @return
      */
-    fun <T : Plugin> load(plugin: T): T {
+    public fun <T : Plugin> load(plugin: T): T {
         if (context.isActive) error("Can't load plugin into active context")
 
         if (get(plugin::class, plugin.tag, recursive = false) != null) {
@@ -107,16 +107,16 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
     /**
      * Load a plugin using its factory
      */
-    fun <T : Plugin> load(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T =
+    public fun <T : Plugin> load(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T =
         load(factory(meta, context))
 
-    fun <T : Plugin> load(factory: PluginFactory<T>, metaBuilder: MetaBuilder.() -> Unit): T =
+    public fun <T : Plugin> load(factory: PluginFactory<T>, metaBuilder: MetaBuilder.() -> Unit): T =
         load(factory, Meta(metaBuilder))
 
     /**
      * Remove a plugin from [PluginManager]
      */
-    fun remove(plugin: Plugin) {
+    public fun remove(plugin: Plugin) {
         if (context.isActive) error("Can't remove plugin from active context")
 
         if (plugins.contains(plugin)) {
@@ -130,7 +130,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
      * Get an existing plugin with given meta or load new one using provided factory
      *
      */
-    fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = Meta.EMPTY): T {
+    public fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = Meta.EMPTY): T {
         val loaded = get(factory.type, factory.tag, recursive)
         return when {
             loaded == null -> load(factory(meta, context))
@@ -139,7 +139,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
         }
     }
 
-    fun <T : Plugin> fetch(
+    public fun <T : Plugin> fetch(
         factory: PluginFactory<T>,
         recursive: Boolean = true,
         metaBuilder: MetaBuilder.() -> Unit
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt
index 06c36ab0..c69e939c 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt
@@ -26,25 +26,25 @@ import hep.dataforge.names.toName
  * @author Alexander Nozik
  * @version $Id: $Id
  */
-inline class Path(val tokens: List<PathToken>) : Iterable<PathToken> {
+public inline class Path(public val tokens: List<PathToken>) : Iterable<PathToken> {
 
-    val head: PathToken? get() = tokens.firstOrNull()
+    public val head: PathToken? get() = tokens.firstOrNull()
 
-    val length: Int get() = tokens.size
+    public val length: Int get() = tokens.size
 
     /**
      * Returns non-empty optional containing the chain without first segment in case of chain path.
      *
      * @return
      */
-    val tail: Path? get() = if (tokens.isEmpty()) null else Path(tokens.drop(1))
+    public val tail: Path? get() = if (tokens.isEmpty()) null else Path(tokens.drop(1))
 
     override fun iterator(): Iterator<PathToken> = tokens.iterator()
 
-    companion object {
-        const val PATH_SEGMENT_SEPARATOR = "/"
+    public companion object {
+        public const val PATH_SEGMENT_SEPARATOR = "/"
 
-        fun parse(path: String): Path {
+        public fun parse(path: String): Path {
             val head = path.substringBefore(PATH_SEGMENT_SEPARATOR)
             val tail = path.substringAfter(PATH_SEGMENT_SEPARATOR)
             return PathToken.parse(head).toPath() + parse(tail)
@@ -52,18 +52,18 @@ inline class Path(val tokens: List<PathToken>) : Iterable<PathToken> {
     }
 }
 
-operator fun Path.plus(path: Path) = Path(this.tokens + path.tokens)
+public operator fun Path.plus(path: Path): Path = Path(this.tokens + path.tokens)
 
-data class PathToken(val name: Name, val target: String? = null) {
+public data class PathToken(val name: Name, val target: String? = null) {
     override fun toString(): String = if (target == null) {
         name.toString()
     } else {
         "$target$TARGET_SEPARATOR$name"
     }
 
-    companion object {
-        const val TARGET_SEPARATOR = "::"
-        fun parse(token: String): PathToken {
+    public companion object {
+        public const val TARGET_SEPARATOR: String = "::"
+        public fun parse(token: String): PathToken {
             val target = token.substringBefore(TARGET_SEPARATOR, "")
             val name = token.substringAfter(TARGET_SEPARATOR).toName()
             if (target.contains("[")) TODO("target separators in queries are not supported")
@@ -72,4 +72,4 @@ data class PathToken(val name: Name, val target: String? = null) {
     }
 }
 
-fun PathToken.toPath() = Path(listOf(this))
+public fun PathToken.toPath(): Path = Path(listOf(this))
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
index bea7b12c..665912b8 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
@@ -22,29 +22,25 @@ import hep.dataforge.names.Name
  *
  * @author Alexander Nozik
  */
-interface Provider {
+public interface Provider {
 
     /**
      * Default target for this provider
-     *
-     * @return
      */
-    val defaultTarget: String get() = ""
+    public val defaultTarget: String get() = ""
 
     /**
      * Default target for next chain segment
-     *
-     * @return
      */
-    val defaultChainTarget: String get() = ""
+    public val defaultChainTarget: String get() = ""
 
     /**
      * A map of direct children for specific target
      */
-    fun provideTop(target: String): Map<Name, Any> = emptyMap()
+    public fun provideTop(target: String): Map<Name, Any> = emptyMap()
 }
 
-fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
+public fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
     if (path.length == 0) throw IllegalArgumentException("Can't provide by empty path")
     val first = path.first()
     val target = targetOverride ?: first.target ?: defaultTarget
@@ -63,7 +59,7 @@ fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
 /**
  * Type checked provide
  */
-inline fun <reified T : Any> Provider.provide(path: String, targetOverride: String? = null): T? {
+public inline fun <reified T : Any> Provider.provide(path: String, targetOverride: String? = null): T? {
     return provide(Path.parse(path), targetOverride) as? T
 }
 //
@@ -77,7 +73,7 @@ inline fun <reified T : Any> Provider.provide(path: String, targetOverride: Stri
 /**
  *  Typed top level content
  */
-inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> {
+public inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> {
     return provideTop(target).mapValues {
         it.value as? T ?: error("The type of element $it is ${it::class} but ${T::class} is expected")
     }
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Type.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Type.kt
index a31f1fdb..e07cfd10 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Type.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Type.kt
@@ -7,4 +7,4 @@ package hep.dataforge.provider
  */
 @MustBeDocumented
 @Target(AnnotationTarget.CLASS)
-annotation class Type(val id: String)
+public annotation class Type(val id: String)
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Action.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Action.kt
index cf030c75..d747587e 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Action.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Action.kt
@@ -5,23 +5,23 @@ import hep.dataforge.meta.Meta
 /**
  * A simple data transformation on a data node
  */
-interface Action<in T : Any, out R : Any> {
+public interface Action<in T : Any, out R : Any> {
     /**
      * Transform the data in the node, producing a new node. By default it is assumed that all calculations are lazy
      * so not actual computation is started at this moment
      */
-    operator fun invoke(node: DataNode<T>, meta: Meta): DataNode<R>
+    public operator fun invoke(node: DataNode<T>, meta: Meta): DataNode<R>
 
     /**
      * Terminal action is the one that could not be invoked lazily and requires some kind of blocking computation to invoke
      */
-    val isTerminal: Boolean get() = false
+    public val isTerminal: Boolean get() = false
 }
 
 /**
  * Action composition. The result is terminal if one of its parts is terminal
  */
-infix fun <T : Any, I : Any, R : Any> Action<T, I>.then(action: Action<I, R>): Action<T, R> {
+public infix fun <T : Any, I : Any, R : Any> Action<T, I>.then(action: Action<I, R>): Action<T, R> {
     // TODO introduce composite action and add optimize by adding action to the list
     return object : Action<T, R> {
         override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/CoroutineMonitor.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/CoroutineMonitor.kt
index 8cbd6192..d1c0d55e 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/CoroutineMonitor.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/CoroutineMonitor.kt
@@ -1,48 +1,58 @@
 package hep.dataforge.data
 
+import hep.dataforge.meta.DFExperimental
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlin.coroutines.CoroutineContext
 
+
+
 /**
  * A monitor of goal state that could be accessed only form inside the goal
  */
-class CoroutineMonitor : CoroutineContext.Element {
+@DFExperimental
+public class CoroutineMonitor : CoroutineContext.Element {
     override val key: CoroutineContext.Key<*> get() = CoroutineMonitor
 
-    var totalWork: Double = 1.0
-    var workDone: Double = 0.0
-    var status: String = ""
+    public var totalWork: Double = 1.0
+    public var workDone: Double = 0.0
+    public var status: String = ""
 
     /**
      * Mark the goal as started
      */
-    fun start() {
+    public fun start() {
 
     }
 
     /**
      * Mark the goal as completed
      */
-    fun finish() {
+    public fun finish() {
         workDone = totalWork
     }
 
-    companion object : CoroutineContext.Key<CoroutineMonitor>
+    public companion object : CoroutineContext.Key<CoroutineMonitor>
 }
 
-class Dependencies(val values: Collection<Job>) : CoroutineContext.Element {
+public class Dependencies(public val values: Collection<Job>) : CoroutineContext.Element {
     override val key: CoroutineContext.Key<*> get() = Dependencies
 
-    companion object : CoroutineContext.Key<Dependencies>
+    public companion object : CoroutineContext.Key<Dependencies>
 }
 
-val CoroutineContext.monitor: CoroutineMonitor? get() = this[CoroutineMonitor]
-val CoroutineScope.monitor: CoroutineMonitor? get() = coroutineContext.monitor
+@DFExperimental
+public val CoroutineContext.monitor: CoroutineMonitor? get() = this[CoroutineMonitor]
+@DFExperimental
+public val CoroutineScope.monitor: CoroutineMonitor? get() = coroutineContext.monitor
 
-val Job.dependencies: Collection<Job> get() = this[Dependencies]?.values ?: emptyList()
+public val Job.dependencies: Collection<Job> get() = this[Dependencies]?.values ?: emptyList()
 
-val Job.totalWork: Double get() = dependencies.sumByDouble { totalWork } + (monitor?.totalWork ?: 0.0)
-val Job.workDone: Double get() = dependencies.sumByDouble { workDone } + (monitor?.workDone ?: 0.0)
-val Job.status: String get() = monitor?.status ?: ""
-val Job.progress: Double get() = workDone / totalWork
\ No newline at end of file
+@DFExperimental
+public val Job.totalWork: Double get() = dependencies.sumByDouble { totalWork } + (monitor?.totalWork ?: 0.0)
+@DFExperimental
+public val Job.workDone: Double get() = dependencies.sumByDouble { workDone } + (monitor?.workDone ?: 0.0)
+@DFExperimental
+public val Job.status: String get() = monitor?.status ?: ""
+@DFExperimental
+public val Job.progress: Double get() = workDone / totalWork
\ No newline at end of file
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt
index 233ea164..c7acf91c 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt
@@ -11,7 +11,7 @@ import kotlin.reflect.KClass
 /**
  * A data element characterized by its meta
  */
-interface Data<out T : Any> : Goal<T>, MetaRepr{
+public interface Data<out T : Any> : Goal<T>, MetaRepr{
     /**
      * Type marker for the data. The type is known before the calculation takes place so it could be checked.
      */
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaConverter.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaConverter.kt
index 931e7cf3..0e4d6261 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaConverter.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaConverter.kt
@@ -6,18 +6,18 @@ import hep.dataforge.values.*
 /**
  * A converter of generic object to and from [MetaItem]
  */
-interface MetaConverter<T : Any> {
-    fun itemToObject(item: MetaItem<*>): T
-    fun objectToMetaItem(obj: T): MetaItem<*>
+public interface MetaConverter<T : Any> {
+    public fun itemToObject(item: MetaItem<*>): T
+    public fun objectToMetaItem(obj: T): MetaItem<*>
 
-    companion object {
+    public companion object {
 
-        val item = object : MetaConverter<MetaItem<*>> {
+        public val item: MetaConverter<MetaItem<*>> = object : MetaConverter<MetaItem<*>> {
             override fun itemToObject(item: MetaItem<*>): MetaItem<*> = item
             override fun objectToMetaItem(obj: MetaItem<*>): MetaItem<*> = obj
         }
 
-        val meta = object : MetaConverter<Meta> {
+        public val meta: MetaConverter<Meta> = object : MetaConverter<Meta> {
             override fun itemToObject(item: MetaItem<*>): Meta = when (item) {
                 is MetaItem.NodeItem -> item.node
                 is MetaItem.ValueItem -> item.value.toMeta()
@@ -26,7 +26,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Meta): MetaItem<*> = MetaItem.NodeItem(obj)
         }
 
-        val value = object : MetaConverter<Value> {
+        public val value: MetaConverter<Value> = object : MetaConverter<Value> {
             override fun itemToObject(item: MetaItem<*>): Value = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -35,7 +35,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Value): MetaItem<*> = MetaItem.ValueItem(obj)
         }
 
-        val string = object : MetaConverter<String> {
+        public val string: MetaConverter<String> = object : MetaConverter<String> {
             override fun itemToObject(item: MetaItem<*>): String = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -44,7 +44,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: String): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val boolean = object : MetaConverter<Boolean> {
+        public val boolean: MetaConverter<Boolean> = object : MetaConverter<Boolean> {
             override fun itemToObject(item: MetaItem<*>): Boolean = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -53,7 +53,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Boolean): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val number = object : MetaConverter<Number> {
+        public val number: MetaConverter<Number> = object : MetaConverter<Number> {
             override fun itemToObject(item: MetaItem<*>): Number = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -62,7 +62,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Number): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val double = object : MetaConverter<Double> {
+        public val double: MetaConverter<Double> = object : MetaConverter<Double> {
             override fun itemToObject(item: MetaItem<*>): Double = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -71,7 +71,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Double): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val float = object : MetaConverter<Float> {
+        public val float: MetaConverter<Float> = object : MetaConverter<Float> {
             override fun itemToObject(item: MetaItem<*>): Float = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -80,7 +80,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Float): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val int = object : MetaConverter<Int> {
+        public val int: MetaConverter<Int> = object : MetaConverter<Int> {
             override fun itemToObject(item: MetaItem<*>): Int = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -89,7 +89,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Int): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val long = object : MetaConverter<Long> {
+        public val long: MetaConverter<Long> = object : MetaConverter<Long> {
             override fun itemToObject(item: MetaItem<*>): Long = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -98,14 +98,14 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Long): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        inline fun <reified E : Enum<E>> enum(): MetaConverter<E> = object : MetaConverter<E> {
+        public inline fun <reified E : Enum<E>> enum(): MetaConverter<E> = object : MetaConverter<E> {
             @Suppress("USELESS_CAST")
             override fun itemToObject(item: MetaItem<*>): E = item.enum<E>() as? E ?: error("The Item is not a Enum")
 
             override fun objectToMetaItem(obj: E): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        fun <T> valueList(writer: (T) -> Value = {Value.of(it)}, reader: (Value) -> T): MetaConverter<List<T>> =
+        public fun <T> valueList(writer: (T) -> Value = {Value.of(it)}, reader: (Value) -> T): MetaConverter<List<T>> =
             object : MetaConverter<List<T>> {
                 override fun itemToObject(item: MetaItem<*>): List<T> =
                     item.value?.list?.map(reader) ?: error("The item is not a value list")
@@ -117,8 +117,8 @@ interface MetaConverter<T : Any> {
     }
 }
 
-fun <T : Any> MetaConverter<T>.nullableItemToObject(item: MetaItem<*>?): T? = item?.let { itemToObject(it) }
-fun <T : Any> MetaConverter<T>.nullableObjectToMetaItem(obj: T?): MetaItem<*>? = obj?.let { objectToMetaItem(it) }
+public fun <T : Any> MetaConverter<T>.nullableItemToObject(item: MetaItem<*>?): T? = item?.let { itemToObject(it) }
+public fun <T : Any> MetaConverter<T>.nullableObjectToMetaItem(obj: T?): MetaItem<*>? = obj?.let { objectToMetaItem(it) }
 
-fun <T : Any> MetaConverter<T>.metaToObject(meta: Meta): T = itemToObject(MetaItem.NodeItem(meta))
-fun <T : Any> MetaConverter<T>.valueToObject(value: Value): T = itemToObject(MetaItem.ValueItem(value))
+public fun <T : Any> MetaConverter<T>.metaToObject(meta: Meta): T = itemToObject(MetaItem.NodeItem(meta))
+public fun <T : Any> MetaConverter<T>.valueToObject(value: Value): T = itemToObject(MetaItem.ValueItem(value))
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt
index 38984520..2c09faa5 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt
@@ -6,31 +6,31 @@ import hep.dataforge.names.Name
 /**
  * A transformation for meta item or a group of items
  */
-interface TransformationRule {
+public interface TransformationRule {
 
     /**
      * Check if this transformation should be applied to a node with given name and value
      */
-    fun matches(name: Name, item: MetaItem<*>?): Boolean
+    public fun matches(name: Name, item: MetaItem<*>?): Boolean
 
     /**
      * Select all items to be transformed. Item could be a value as well as node
      *
      * @return a sequence of item paths to be transformed
      */
-    fun selectItems(meta: Meta): Sequence<Name> =
+    public fun selectItems(meta: Meta): Sequence<Name> =
         meta.sequence().filter { matches(it.first, it.second) }.map { it.first }
 
     /**
      * Apply transformation for a single item (Node or Value) to the target
      */
-    fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit
+    public fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit
 }
 
 /**
  * A transformation which keeps all elements, matching [selector] unchanged.
  */
-data class KeepTransformationRule(val selector: (Name) -> Boolean) :
+public data class KeepTransformationRule(val selector: (Name) -> Boolean) :
     TransformationRule {
     override fun matches(name: Name, item: MetaItem<*>?): Boolean {
         return selector(name)
@@ -47,7 +47,7 @@ data class KeepTransformationRule(val selector: (Name) -> Boolean) :
 /**
  * A transformation which transforms element with specific name
  */
-data class SingleItemTransformationRule(
+public data class SingleItemTransformationRule(
     val from: Name,
     val transform: MutableMeta<*>.(Name, MetaItem<*>?) -> Unit
 ) : TransformationRule {
@@ -64,7 +64,7 @@ data class SingleItemTransformationRule(
     }
 }
 
-data class RegexItemTransformationRule(
+public data class RegexItemTransformationRule(
     val from: Regex,
     val transform: MutableMeta<*>.(name: Name, MatchResult, MetaItem<*>?) -> Unit
 ) : TransformationRule {
@@ -84,12 +84,12 @@ data class RegexItemTransformationRule(
 /**
  * A set of [TransformationRule] to either transform static meta or create dynamically updated [MutableMeta]
  */
-inline class MetaTransformation(val transformations: Collection<TransformationRule>) {
+public inline class MetaTransformation(public val transformations: Collection<TransformationRule>) {
 
     /**
      * Produce new meta using only those items that match transformation rules
      */
-    fun generate(source: Meta): Meta =
+    public fun generate(source: Meta): Meta =
         Meta {
             transformations.forEach { rule ->
                 rule.selectItems(source).forEach { name ->
@@ -102,7 +102,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
      * Generate an observable configuration that contains only elements defined by transformation rules and changes with the source
      */
     @DFExperimental
-    fun generate(source: Config): ObservableMeta = Config().apply {
+    public fun generate(source: Config): ObservableMeta = Config().apply {
         transformations.forEach { rule ->
             rule.selectItems(source).forEach { name ->
                 rule.transformItem(name, source[name], this)
@@ -115,7 +115,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
     /**
      * Transform a meta, replacing all elements found in rules with transformed entries
      */
-    fun apply(source: Meta): Meta =
+    public fun apply(source: Meta): Meta =
         source.edit {
             transformations.forEach { rule ->
                 rule.selectItems(source).forEach { name ->
@@ -128,7 +128,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
     /**
      * Listens for changes in the source node and translates them into second node if transformation set contains a corresponding rule.
      */
-    fun <M : MutableMeta<M>> bind(source: Config, target: M) {
+    public fun <M : MutableMeta<M>> bind(source: Config, target: M) {
         source.onChange(target) { name, _, newItem ->
             transformations.forEach { t ->
                 if (t.matches(name, newItem)) {
@@ -147,27 +147,27 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
 /**
  * A builder for a set of transformation rules
  */
-class MetaTransformationBuilder {
-    val transformations = HashSet<TransformationRule>()
+public class MetaTransformationBuilder {
+    private val transformations = HashSet<TransformationRule>()
 
     /**
      * Keep all items with name satisfying the criteria
      */
-    fun keep(selector: (Name) -> Boolean) {
+    public fun keep(selector: (Name) -> Boolean) {
         transformations.add(KeepTransformationRule(selector))
     }
 
     /**
      * Keep specific item (including its descendants)
      */
-    fun keep(name: Name) {
+    public fun keep(name: Name) {
         keep { it == name }
     }
 
     /**
      * Keep nodes by regex
      */
-    fun keep(regex: String) {
+    public fun keep(regex: String) {
         transformations.add(
             RegexItemTransformationRule(regex.toRegex()) { name, _, metaItem ->
                 setItem(name, metaItem)
@@ -177,7 +177,7 @@ class MetaTransformationBuilder {
     /**
      * Move an item from [from] to [to], optionally applying [operation] it defined
      */
-    fun move(from: Name, to: Name, operation: (MetaItem<*>?) -> Any? = { it }) {
+    public fun move(from: Name, to: Name, operation: (MetaItem<*>?) -> Any? = { it }) {
         transformations.add(
             SingleItemTransformationRule(from) { _, item ->
                 set(to, operation(item))
@@ -185,5 +185,5 @@ class MetaTransformationBuilder {
         )
     }
 
-    fun build() = MetaTransformation(transformations)
+    public fun build(): MetaTransformation = MetaTransformation(transformations)
 }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt
index 07e66ea8..2171c4ea 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt
@@ -13,7 +13,7 @@ public fun Value.isNull(): Boolean = this == Null
  */
 public fun Value.isList(): Boolean = this.list.size > 1
 
-public val Value.boolean
+public val Value.boolean: Boolean
     get() = this == True
             || this.list.firstOrNull() == True
             || (type == ValueType.STRING && string.toBoolean())
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
index f608b59d..02452ce6 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
@@ -35,7 +35,7 @@ public abstract class WorkspacePlugin : AbstractPlugin() {
     public inline fun <reified T : Any> task(
         name: String,
         noinline builder: TaskBuilder<T>.() -> Unit
-    ) = task(name, T::class, builder)
+    ): GenericTask<T> = task(name, T::class, builder)
 
 //
 ////TODO add delegates to build gradle-like tasks

From b229de3eb7f711120b14735c41c3e54ee7aa899b Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sun, 13 Sep 2020 19:35:58 +0300
Subject: [PATCH 22/40] Context content resolution refactor. Explicit API mode.

---
 CHANGELOG.md                                  |   5 +
 dataforge-context/build.gradle.kts            |   6 +-
 .../kotlin/hep/dataforge/context/Context.kt   |  79 +++++++-------
 .../hep/dataforge/context/ContextBuilder.kt   |  13 ++-
 .../kotlin/hep/dataforge/context/Global.kt    |   3 +-
 .../kotlin/hep/dataforge/context/Plugin.kt    |  13 +--
 .../hep/dataforge/context/PluginManager.kt    |  28 +++--
 .../kotlin/hep/dataforge/context/resolve.kt   |  96 +++++++++++++++++
 .../kotlin/hep/dataforge/provider/Path.kt     |   2 +-
 .../kotlin/hep/dataforge/provider/Provider.kt |  19 ++--
 .../hep/dataforge/context/ContextTest.kt      |   4 +-
 .../kotlin/hep/dataforge/provider/Types.kt    |  44 --------
 .../kotlin/hep/dataforge/provider/dfType.kt   |  36 +++++++
 .../kotlin/hep/dataforge/data/Data.kt         |  35 +++---
 .../kotlin/hep/dataforge/data/DataFilter.kt   |  12 +--
 .../kotlin/hep/dataforge/data/DataNode.kt     | 102 +++++++++---------
 .../kotlin/hep/dataforge/data/Goal.kt         |  34 +++---
 .../kotlin/hep/dataforge/data/GroupRule.kt    |  10 +-
 .../kotlin/hep/dataforge/data/MapAction.kt    |  17 ++-
 .../kotlin/hep/dataforge/data/ReduceAction.kt |  26 ++---
 .../kotlin/hep/dataforge/data/SplitAction.kt  |  16 +--
 .../kotlin/hep/dataforge/data/dataCast.kt     |  16 +--
 .../dataforge/data/TypeFilteredDataNode.kt    |   2 +-
 .../kotlin/hep/dataforge/data/dataJVM.kt      |   4 +-
 .../kotlin/hep/dataforge/io/IOPlugin.kt       |  10 +-
 .../kotlin/hep/dataforge/meta/Laminate.kt     |   5 +-
 .../kotlin/hep/dataforge/values/Value.kt      |   2 +-
 .../hep/dataforge/workspace/Workspace.kt      |   2 +-
 .../dataforge/workspace/WorkspacePlugin.kt    |   2 +-
 settings.gradle.kts                           |   4 +-
 30 files changed, 372 insertions(+), 275 deletions(-)
 create mode 100644 dataforge-context/src/commonMain/kotlin/hep/dataforge/context/resolve.kt
 delete mode 100644 dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
 create mode 100644 dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/dfType.kt

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b08d3d08..35d67eee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,15 +4,20 @@
 ### Added
 
 ### Changed
+- Context content resolution refactor
+- Kotlin 1.4.10 (build tools 0.6.0)
 - Empty query in Name is null instead of ""
 - Provider provides an empty map instead of error by default
+- Hidden delegates hierarchy in favor of stdlib properties
 
 ### Deprecated
+- Context activation API
 
 ### Removed
 - Functional server prototype
 
 ### Fixed
 - Global context CoroutineScope resolution
+- Library mode compliance
 
 ### Security
diff --git a/dataforge-context/build.gradle.kts b/dataforge-context/build.gradle.kts
index 3ef9f80f..c8e3e588 100644
--- a/dataforge-context/build.gradle.kts
+++ b/dataforge-context/build.gradle.kts
@@ -10,16 +10,12 @@ kscience {
     useCoroutines()
 }
 
-repositories {
-    maven("https://maven.pkg.github.com/altavir/kotlin-logging")
-}
-
 kotlin {
     sourceSets {
         val commonMain by getting {
             dependencies {
                 api(project(":dataforge-meta"))
-                api("io.github.microutils:kotlin-logging:1.9.0-dev-npm")
+                api("io.github.microutils:kotlin-logging:1.9.0-dev-npm-2")
             }
         }
         val jvmMain by getting {
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
index f9f07aef..640c7b5a 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
@@ -1,18 +1,18 @@
 package hep.dataforge.context
 
-import hep.dataforge.meta.*
+import hep.dataforge.meta.Laminate
+import hep.dataforge.meta.Meta
+import hep.dataforge.meta.MetaRepr
+import hep.dataforge.meta.sequence
 import hep.dataforge.names.Name
 import hep.dataforge.names.plus
 import hep.dataforge.provider.Provider
-import hep.dataforge.provider.top
-import hep.dataforge.values.Value
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.SupervisorJob
 import mu.KLogger
 import mu.KotlinLogging
 import kotlin.coroutines.CoroutineContext
-import kotlin.jvm.JvmName
 
 /**
  * The local environment for anything being done in DataForge framework. Contexts are organized into tree structure with [Global] at the top.
@@ -23,23 +23,20 @@ import kotlin.jvm.JvmName
  * different plugins with the same interface in different contexts in the hierarchy. The usual behaviour is to use nearest one, but it could
  * be overridden by plugin implementation.
  *
- * Since plugins could contain mutable state, context has two states: active and inactive. No changes are allowed to active context.
- * @author Alexander Nozik
  */
 public open class Context(
     final override val name: Name,
-    public val parent: Context? = Global,
+    public val parent: Context?,
+    meta: Meta,
 ) : Named, MetaRepr, Provider, CoroutineScope {
 
-    private val config = Config()
-
     /**
      * Context properties. Working as substitute for environment variables
      */
-    private val properties: Meta = if (parent == null) {
-        config
+    private val properties: Laminate = if (parent == null) {
+        Laminate(meta)
     } else {
-        Laminate(config, parent.properties)
+        Laminate(meta, parent.properties)
     }
 
     /**
@@ -52,26 +49,19 @@ public open class Context(
      */
     public val plugins: PluginManager by lazy { PluginManager(this) }
 
+    @Deprecated("To be removed in favor of immutable plugins")
     private val activators = HashSet<Any>()
 
     /**
      * Defines if context is used in any kind of active computations. Active context properties and plugins could not be changed
      */
+    @Deprecated("To be removed in favor of immutable plugins")
     public val isActive: Boolean = activators.isNotEmpty()
 
-    override val defaultTarget: String get() = Plugin.PLUGIN_TARGET
-
-    override fun provideTop(target: String): Map<Name, Any> {
-        return when (target) {
-            Value.TYPE -> properties.sequence().toMap()
-            Plugin.PLUGIN_TARGET -> plugins.sequence(true).associateBy { it.name }
-            else -> emptyMap()
-        }
-    }
-
     /**
      * Mark context as active and used by [activator]
      */
+    @Deprecated("To be removed in favor of immutable plugins")
     public fun activate(activator: Any) {
         activators.add(activator)
     }
@@ -79,19 +69,32 @@ public open class Context(
     /**
      * Mark context unused by [activator]
      */
+    @Deprecated("To be removed in favor of immutable plugins")
     public fun deactivate(activator: Any) {
         activators.remove(activator)
     }
 
-    /**
-     * Change the properties of the context. If active, throw an exception
-     */
-    public fun configure(action: Config.() -> Unit) {
-        if (isActive) error("Can't configure active context")
-        config.action()
+    override val defaultTarget: String get() = Plugin.TARGET
+
+    public fun content(target: String, inherit: Boolean): Map<Name, Any> {
+        return if (inherit) {
+            when (target) {
+                PROPERTY_TARGET -> properties.sequence().toMap()
+                Plugin.TARGET -> plugins.list(true).associateBy { it.name }
+                else -> emptyMap()
+            }
+        } else {
+            when (target) {
+                PROPERTY_TARGET -> properties.layers.firstOrNull()?.sequence()?.toMap() ?: emptyMap()
+                Plugin.TARGET -> plugins.list(false).associateBy { it.name }
+                else -> emptyMap()
+            }
+        }
     }
 
-    open override val coroutineContext: CoroutineContext by lazy {
+    override fun content(target: String): Map<Name, Any>  = content(target,true)
+
+    override val coroutineContext: CoroutineContext by lazy {
         (parent ?: Global).coroutineContext.let { parenContext ->
             parenContext + SupervisorJob(parenContext[Job])
         }
@@ -101,6 +104,7 @@ public open class Context(
      * Detach all plugins and terminate context
      */
     public open fun close() {
+        @Suppress("DEPRECATION")
         if (isActive) error("Can't close active context")
         //detach all plugins
         plugins.forEach { it.detach() }
@@ -108,22 +112,15 @@ public open class Context(
 
     override fun toMeta(): Meta = Meta {
         "parent" to parent?.name
-        "properties" put properties.seal()
+        "properties" put properties.layers.firstOrNull()
         "plugins" put plugins.map { it.toMeta() }
     }
+
+    public companion object {
+        public const val PROPERTY_TARGET: String = "context.property"
+    }
 }
 
-/**
- * A map of all objects provided by plugins with given target and type
- */
-@JvmName("typedContent")
-public inline fun <reified T : Any> Context.resolve(target: String): Map<Name, T> = plugins.flatMap { plugin ->
-    plugin.top<T>(target).entries.map { (plugin.name + it.key) to it.value }
-}.associate { it }
-
-
-public fun Context.resolve(target: String): Map<Name, Any> = resolve<Any>(target)
-
 /**
  * The interface for something that encapsulated in context
  *
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
index ecb6726e..75bd6c5d 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
@@ -1,8 +1,6 @@
 package hep.dataforge.context
 
-import hep.dataforge.meta.DFBuilder
-import hep.dataforge.meta.Meta
-import hep.dataforge.meta.MetaBuilder
+import hep.dataforge.meta.*
 import hep.dataforge.names.toName
 
 /**
@@ -21,10 +19,11 @@ public class ContextBuilder(private val parent: Context = Global, public var nam
         plugins.add(plugin)
     }
 
-    public fun plugin(tag: PluginTag, action: MetaBuilder.() -> Unit = {}) {
-        val factory = parent.resolve<PluginFactory<*>>(PluginFactory.TYPE).values
+    @OptIn(DFExperimental::class)
+    public fun plugin(tag: PluginTag, metaBuilder: MetaBuilder.() -> Unit = {}) {
+        val factory = parent.gatherInSequence<PluginFactory<*>>(PluginFactory.TYPE).values
             .find { it.tag.matches(tag) } ?: error("Can't resolve plugin factory for $tag")
-        val plugin = factory.invoke(Meta(action), parent)
+        val plugin = factory.invoke(Meta(metaBuilder), parent)
         plugins.add(plugin)
     }
 
@@ -37,7 +36,7 @@ public class ContextBuilder(private val parent: Context = Global, public var nam
     }
 
     public fun build(): Context {
-        return Context(name.toName(), parent).apply {
+        return Context(name.toName(), parent, meta.seal()).apply {
             this@ContextBuilder.plugins.forEach {
                 plugins.load(it)
             }
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
index d7a52c46..4666fb78 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
@@ -1,5 +1,6 @@
 package hep.dataforge.context
 
+import hep.dataforge.meta.Meta
 import hep.dataforge.names.asName
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.SupervisorJob
@@ -8,7 +9,7 @@ import kotlin.coroutines.CoroutineContext
 /**
  * A global root context. Closing [Global] terminates the framework.
  */
-public object Global : Context("GLOBAL".asName(), null) {
+public object Global : Context("GLOBAL".asName(), null, Meta.EMPTY) {
 
     override val coroutineContext: CoroutineContext = GlobalScope.coroutineContext + SupervisorJob()
 
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
index b8bc6601..ff0e3a0c 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
@@ -1,27 +1,23 @@
 package hep.dataforge.context
 
+import hep.dataforge.context.Plugin.Companion.TARGET
 import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaRepr
 import hep.dataforge.names.Name
 import hep.dataforge.names.toName
 import hep.dataforge.provider.Provider
+import hep.dataforge.provider.Type
 
 /**
  * The interface to define a Context plugin. A plugin stores all runtime features of a context.
  * The plugin is by default configurable and a Provider (both features could be ignored).
  * The plugin must in most cases have an empty constructor in order to be able to load it from library.
  *
- *
  * The plugin lifecycle is the following:
  *
- *
  * create - configure - attach - detach - destroy
- *
- *
- * Configuration of attached plugin is possible for a context which is not in a runtime mode, but it is not recommended.
- *
- * @author Alexander Nozik
  */
+@Type(TARGET)
 public interface Plugin : Named, ContextAware, Provider, MetaRepr {
 
     /**
@@ -64,8 +60,7 @@ public interface Plugin : Named, ContextAware, Provider, MetaRepr {
     }
 
     public companion object {
-
-        public const val PLUGIN_TARGET = "plugin"
+        public const val TARGET: String = "plugin"
     }
 
 }
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
index dadb333e..cdae4f53 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
@@ -2,14 +2,16 @@ package hep.dataforge.context
 
 import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaBuilder
+import hep.dataforge.provider.Type
 import kotlin.reflect.KClass
 
 
+@Type(PluginFactory.TYPE)
 public interface PluginFactory<T : Plugin> : Factory<T> {
     public val tag: PluginTag
     public val type: KClass<out T>
 
-    public companion object{
+    public companion object {
         public const val TYPE: String = "pluginFactory"
     }
 }
@@ -23,6 +25,8 @@ public interface PluginFactory<T : Plugin> : Factory<T> {
  */
 public class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
 
+    //TODO refactor to read-only container
+
     /**
      * A set of loaded plugins
      */
@@ -33,21 +37,24 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
      */
     private val parent: PluginManager? = context.parent?.plugins
 
-
-    public fun sequence(recursive: Boolean): Sequence<Plugin> {
-        return if (recursive && parent != null) {
-            plugins.asSequence() + parent.sequence(true)
+    /**
+     * List plugins stored in this [PluginManager]. If [inherit] is true, include parent plugins as well
+     */
+    public fun list(inherit: Boolean): Collection<Plugin> {
+        return if (inherit && parent != null) {
+            plugins + parent.list(true)
         } else {
-            plugins.asSequence()
+            plugins
         }
     }
 
     /**
      * Get existing plugin or return null if not present. Only first matching plugin is returned.
-     * @param recursive search for parent [PluginManager] plugins
+     * @param inherit search for parent [PluginManager] plugins
      * @param predicate condition for the plugin
      */
-    public fun find(recursive: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? = sequence(recursive).find(predicate)
+    public fun find(inherit: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? =
+        list(inherit).find(predicate)
 
 
     /**
@@ -56,7 +63,8 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
      * @param tag
      * @return
      */
-    public operator fun get(tag: PluginTag, recursive: Boolean = true): Plugin? = find(recursive) { tag.matches(it.tag) }
+    public operator fun get(tag: PluginTag, inherit: Boolean = true): Plugin? =
+        find(inherit) { tag.matches(it.tag) }
 
 
     /**
@@ -142,7 +150,7 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
     public fun <T : Plugin> fetch(
         factory: PluginFactory<T>,
         recursive: Boolean = true,
-        metaBuilder: MetaBuilder.() -> Unit
+        metaBuilder: MetaBuilder.() -> Unit,
     ): T = fetch(factory, recursive, Meta(metaBuilder))
 
     override fun iterator(): Iterator<Plugin> = plugins.iterator()
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/resolve.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/resolve.kt
new file mode 100644
index 00000000..811220af
--- /dev/null
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/resolve.kt
@@ -0,0 +1,96 @@
+package hep.dataforge.context
+
+import hep.dataforge.meta.DFExperimental
+import hep.dataforge.names.Name
+import hep.dataforge.names.plus
+import hep.dataforge.provider.Provider
+import hep.dataforge.provider.top
+import kotlin.reflect.KClass
+import kotlin.reflect.cast
+
+/**
+ * Resolve a specific element in top level elements of the provider and attempt to cast it to the given type
+ */
+private fun <T : Any> Provider.provide(target: String, name: Name, type: KClass<out T>): T? {
+    return content(target)[name]?.let { type.cast(it) }
+}
+
+/**
+ * Resolve a top level object with given [target] and [name] in a [Context] own scope or its plugins.
+ */
+public fun <T : Any> Context.resolve(target: String, name: Name, type: KClass<out T>): T? {
+    //Try searching for plugin an context property
+    provide(target, name, type)?.let { return it }
+    val pluginContent = plugins.mapNotNull { it.provide(target, name, type) }
+    return if (pluginContent.isEmpty()) {
+        parent?.resolve<T>(target, name, type)
+    } else {
+        pluginContent.single() // throws error in case of name/type conflicts
+    }
+}
+
+/**
+ * Resolve a top level object with given [target] and [name] in a [Context] own scope or its plugins.
+ */
+public inline fun <reified T : Any> Context.resolve(target: String, name: Name): T? =
+    resolve(target, name, T::class)
+
+/**
+ * Gather a map of all top-level objects with given [target] from context plugins.
+ * Content from plugins is prefixed by plugin name so name conflicts are impossible
+ * This operation could be slow in case of large number of plugins
+ */
+public fun <T : Any> Context.gather(
+    target: String,
+    type: KClass<out T>,
+    inherit: Boolean = true,
+): Map<Name, T> = buildMap {
+    putAll(top(target, type))
+    plugins.forEach { plugin ->
+        plugin.top(target, type).forEach { (name, value) ->
+            if (containsKey(name)) error("Name conflict during gather. An item with name $name could not be gathered from $plugin because key is already present.")
+            put(plugin.name + name, value)
+        }
+    }
+    if (inherit) {
+        parent?.gather(target, type, inherit)?.forEach {
+            //put all values from parent if they are not conflicting
+            if (!containsKey(it.key)) {
+                put(it.key, it.value)
+            }
+        }
+    }
+}
+
+public inline fun <reified T : Any> Context.gather(target: String, inherit: Boolean = true): Map<Name, T> =
+    gather(target, T::class, inherit)
+
+/**
+ * Gather all content from context itself and its plugins in a form of sequence of name-value pairs. Ignores name conflicts.
+ *
+ * Adds parent context sequence as well if [inherit] is true
+ */
+@DFExperimental
+public fun <T : Any> Context.gatherInSequence(
+    target: String,
+    type: KClass<out T>,
+    inherit: Boolean = true,
+): Sequence<Map.Entry<Name, T>> = sequence {
+    yieldAll(top(target, type).entries)
+    plugins.forEach { plugin ->
+        yieldAll(plugin.top(target, type).mapKeys { plugin.name + it.key }.entries)
+    }
+    if (inherit) {
+        parent?.gather(target, type, inherit)?.let {
+            yieldAll(it.entries)
+        }
+    }
+}
+
+@DFExperimental
+public inline fun <reified T : Any> Context.gatherInSequence(
+    target: String,
+    inherit: Boolean = true,
+): Sequence<Map.Entry<Name, T>> = gatherInSequence(target, T::class, inherit)
+
+public val <T> Sequence<Map.Entry<Name, T>>.values: Sequence<T> get() = map { it.value }
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt
index c69e939c..6cd0d7fa 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt
@@ -42,7 +42,7 @@ public inline class Path(public val tokens: List<PathToken>) : Iterable<PathToke
     override fun iterator(): Iterator<PathToken> = tokens.iterator()
 
     public companion object {
-        public const val PATH_SEGMENT_SEPARATOR = "/"
+        public const val PATH_SEGMENT_SEPARATOR: String = "/"
 
         public fun parse(path: String): Path {
             val head = path.substringBefore(PATH_SEGMENT_SEPARATOR)
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
index 665912b8..3a153d86 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
@@ -16,6 +16,8 @@
 package hep.dataforge.provider
 
 import hep.dataforge.names.Name
+import kotlin.reflect.KClass
+import kotlin.reflect.safeCast
 
 /**
  * A marker utility interface for providers.
@@ -37,14 +39,14 @@ public interface Provider {
     /**
      * A map of direct children for specific target
      */
-    public fun provideTop(target: String): Map<Name, Any> = emptyMap()
+    public fun content(target: String): Map<Name, Any> = emptyMap()
 }
 
 public fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
     if (path.length == 0) throw IllegalArgumentException("Can't provide by empty path")
     val first = path.first()
     val target = targetOverride ?: first.target ?: defaultTarget
-    val res = provideTop(target)[first.name] ?: return null
+    val res = content(target)[first.name] ?: return null
     return when (path.length) {
         1 -> res
         else -> {
@@ -66,17 +68,22 @@ public inline fun <reified T : Any> Provider.provide(path: String, targetOverrid
 //inline fun <reified T : Any> Provider.provide(target: String, name: Name): T? {
 //    return provide(PathToken(name, target).toPath()) as? T
 //}
-//
+
 //inline fun <reified T : Any> Provider.provide(target: String, name: String): T? =
 //    provide(target, name.toName())
 
 /**
  *  Typed top level content
  */
-public inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> {
-    return provideTop(target).mapValues {
-        it.value as? T ?: error("The type of element $it is ${it::class} but ${T::class} is expected")
+public fun <T : Any> Provider.top(target: String, type: KClass<out T>): Map<Name, T> {
+    return content(target).mapValues {
+        type.safeCast(it.value) ?: error("The type of element $it is ${it::class} but $type is expected")
     }
 }
 
+/**
+ *  Typed top level content
+ */
+public inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> = top(target, T::class)
+
 
diff --git a/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt b/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
index ba7e17de..ef3d1254 100644
--- a/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
+++ b/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
@@ -11,7 +11,7 @@ class ContextTest {
     class DummyPlugin : AbstractPlugin() {
         override val tag get() = PluginTag("test")
 
-        override fun provideTop(target: String): Map<Name, Any> {
+        override fun content(target: String): Map<Name, Any> {
             return when(target){
                 "test" -> listOf("a", "b", "c.d").associate { it.toName() to it.toName() }
                 else -> emptyMap()
@@ -22,7 +22,7 @@ class ContextTest {
     @Test
     fun testPluginManager() {
         Global.plugins.load(DummyPlugin())
-        val members = Global.resolve<Name>("test")
+        val members = Global.gather<Name>("test")
         assertEquals(3, members.count())
         members.forEach {
             assertEquals(it.key, it.value.appendLeft("test"))
diff --git a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
deleted file mode 100644
index 232e2655..00000000
--- a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package hep.dataforge.provider
-
-import hep.dataforge.context.Context
-import hep.dataforge.context.resolve
-import hep.dataforge.names.Name
-import kotlin.reflect.KClass
-import kotlin.reflect.full.findAnnotation
-
-/**
- *
- */
-object Types {
-    operator fun get(cl: KClass<*>): String {
-        return cl.findAnnotation<Type>()?.id ?: cl.simpleName ?: ""
-    }
-
-    operator fun get(obj: Any): String {
-        return get(obj::class)
-    }
-}
-
-/**
- * Provide an object with given name inferring target from its type using [Type] annotation
- */
-inline fun <reified T : Any> Provider.provideByType(name: String): T? {
-    val target = Types[T::class]
-    return provide(target, name)
-}
-//
-//inline fun <reified T : Any> Provider.provideByType(name: Name): T? {
-//    val target = Types[T::class]
-//    return provide(target, name)
-//}
-
-inline fun <reified T : Any> Provider.top(): Map<Name, T> {
-    val target = Types[T::class]
-    return top(target)
-}
-
-/**
- * A sequences of all objects provided by plugins with given target and type
- */
-inline fun <reified T : Any> Context.content(): Map<Name, T> = resolve<T>(Types[T::class])
-
diff --git a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/dfType.kt b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/dfType.kt
new file mode 100644
index 00000000..9c08d6a8
--- /dev/null
+++ b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/dfType.kt
@@ -0,0 +1,36 @@
+package hep.dataforge.provider
+
+import hep.dataforge.context.Context
+import hep.dataforge.context.gather
+import hep.dataforge.meta.DFExperimental
+import hep.dataforge.names.Name
+import kotlin.reflect.KClass
+import kotlin.reflect.full.findAnnotation
+
+
+@DFExperimental
+public val KClass<*>.dfType: String
+    get() = findAnnotation<Type>()?.id ?: simpleName ?: ""
+
+/**
+ * Provide an object with given name inferring target from its type using [Type] annotation
+ */
+@DFExperimental
+public inline fun <reified T : Any> Provider.provideByType(name: String): T? {
+    val target = T::class.dfType
+    return provide(target, name)
+}
+
+@DFExperimental
+public inline fun <reified T : Any> Provider.top(): Map<Name, T> {
+    val target = T::class.dfType
+    return top(target)
+}
+
+/**
+ * All objects provided by plugins with given target and type
+ */
+@DFExperimental
+public inline fun <reified T : Any> Context.gather(inherit: Boolean = true): Map<Name, T> =
+    gather<T>(T::class.dfType, inherit)
+
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt
index c7acf91c..c573aad8 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt
@@ -15,11 +15,12 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
     /**
      * Type marker for the data. The type is known before the calculation takes place so it could be checked.
      */
-    val type: KClass<out T>
+    public val type: KClass<out T>
+
     /**
      * Meta for the data
      */
-    val meta: Meta
+    public val meta: Meta
 
     override fun toMeta(): Meta  = Meta {
         "type" put (type.simpleName?:"undefined")
@@ -28,10 +29,10 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
         }
     }
 
-    companion object {
-        const val TYPE = "data"
+    public companion object {
+        public const val TYPE: String = "data"
 
-        operator fun <T : Any> invoke(
+        public operator fun <T : Any> invoke(
             type: KClass<out T>,
             meta: Meta = Meta.EMPTY,
             context: CoroutineContext = EmptyCoroutineContext,
@@ -39,14 +40,14 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
             block: suspend CoroutineScope.() -> T
         ): Data<T> = DynamicData(type, meta, context, dependencies, block)
 
-        inline operator fun <reified T : Any> invoke(
+        public inline operator fun <reified T : Any> invoke(
             meta: Meta = Meta.EMPTY,
             context: CoroutineContext = EmptyCoroutineContext,
             dependencies: Collection<Data<*>> = emptyList(),
             noinline block: suspend CoroutineScope.() -> T
         ): Data<T> = invoke(T::class, meta, context, dependencies, block)
 
-        operator fun <T : Any> invoke(
+        public operator fun <T : Any> invoke(
             name: String,
             type: KClass<out T>,
             meta: Meta = Meta.EMPTY,
@@ -55,7 +56,7 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
             block: suspend CoroutineScope.() -> T
         ): Data<T> = NamedData(name, invoke(type, meta, context, dependencies, block))
 
-        inline operator fun <reified T : Any> invoke(
+        public inline operator fun <reified T : Any> invoke(
             name: String,
             meta: Meta = Meta.EMPTY,
             context: CoroutineContext = EmptyCoroutineContext,
@@ -64,13 +65,13 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
         ): Data<T> =
             invoke(name, T::class, meta, context, dependencies, block)
 
-        fun <T : Any> static(value: T, meta: Meta = Meta.EMPTY): Data<T> =
+        public fun <T : Any> static(value: T, meta: Meta = Meta.EMPTY): Data<T> =
             StaticData(value, meta)
     }
 }
 
 
-class DynamicData<T : Any>(
+public class DynamicData<T : Any>(
     override val type: KClass<out T>,
     override val meta: Meta = Meta.EMPTY,
     context: CoroutineContext = EmptyCoroutineContext,
@@ -78,16 +79,16 @@ class DynamicData<T : Any>(
     block: suspend CoroutineScope.() -> T
 ) : Data<T>, DynamicGoal<T>(context, dependencies, block)
 
-class StaticData<T : Any>(
+public class StaticData<T : Any>(
     value: T,
     override val meta: Meta = Meta.EMPTY
 ) : Data<T>, StaticGoal<T>(value) {
     override val type: KClass<out T> get() = value::class
 }
 
-class NamedData<out T : Any>(val name: String, data: Data<T>) : Data<T> by data
+public class NamedData<out T : Any>(public val name: String, data: Data<T>) : Data<T> by data
 
-fun <T : Any, R : Any> Data<T>.map(
+public fun <T : Any, R : Any> Data<T>.map(
     outputType: KClass<out R>,
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     meta: Meta = this.meta,
@@ -100,7 +101,7 @@ fun <T : Any, R : Any> Data<T>.map(
 /**
  * Create a data pipe
  */
-inline fun <T : Any, reified R : Any> Data<T>.map(
+public inline fun <T : Any, reified R : Any> Data<T>.map(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     meta: Meta = this.meta,
     noinline block: suspend CoroutineScope.(T) -> R
@@ -111,7 +112,7 @@ inline fun <T : Any, reified R : Any> Data<T>.map(
 /**
  * Create a joined data.
  */
-inline fun <T : Any, reified R : Any> Collection<Data<T>>.reduce(
+public inline fun <T : Any, reified R : Any> Collection<Data<T>>.reduce(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     meta: Meta,
     noinline block: suspend CoroutineScope.(Collection<T>) -> R
@@ -124,7 +125,7 @@ inline fun <T : Any, reified R : Any> Collection<Data<T>>.reduce(
     block(map { run { it.await() } })
 }
 
-fun <K, T : Any, R : Any> Map<K, Data<T>>.reduce(
+public fun <K, T : Any, R : Any> Map<K, Data<T>>.reduce(
     outputType: KClass<out R>,
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     meta: Meta,
@@ -145,7 +146,7 @@ fun <K, T : Any, R : Any> Map<K, Data<T>>.reduce(
  * @param T type of the input goal
  * @param R type of the result goal
  */
-inline fun <K, T : Any, reified R : Any> Map<K, Data<T>>.reduce(
+public inline fun <K, T : Any, reified R : Any> Map<K, Data<T>>.reduce(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     meta: Meta,
     noinline block: suspend CoroutineScope.(Map<K, T>) -> R
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
index b24f87a2..79f790ab 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
@@ -4,25 +4,25 @@ import hep.dataforge.meta.*
 import hep.dataforge.names.toName
 
 
-class DataFilter : Scheme() {
+public class DataFilter : Scheme() {
     /**
      * A source node for the filter
      */
-    var from by string()
+    public var from: String? by string()
     /**
      * A target placement for the filtered node
      */
-    var to by string()
+    public var to: String? by string()
     /**
      * A regular expression pattern for the filter
      */
-    var pattern by string(".*")
+    public var pattern: String by string(".*")
 //    val prefix by string()
 //    val suffix by string()
 
-    fun isEmpty(): Boolean = config.isEmpty()
+    public fun isEmpty(): Boolean = config.isEmpty()
 
-    companion object : SchemeSpec<DataFilter>(::DataFilter)
+    public companion object : SchemeSpec<DataFilter>(::DataFilter)
 }
 
 /**
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt
index 1eac4745..23fea9ef 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt
@@ -11,12 +11,12 @@ import kotlin.collections.component2
 import kotlin.collections.set
 import kotlin.reflect.KClass
 
-sealed class DataItem<out T : Any> : MetaRepr {
-    abstract val type: KClass<out T>
+public sealed class DataItem<out T : Any> : MetaRepr {
+    public abstract val type: KClass<out T>
 
-    abstract val meta: Meta
+    public abstract val meta: Meta
 
-    class Node<out T : Any>(val node: DataNode<T>) : DataItem<T>() {
+    public class Node<out T : Any>(public val node: DataNode<T>) : DataItem<T>() {
         override val type: KClass<out T> get() = node.type
 
         override fun toMeta(): Meta = node.toMeta()
@@ -24,7 +24,7 @@ sealed class DataItem<out T : Any> : MetaRepr {
         override val meta: Meta get() = node.meta
     }
 
-    class Leaf<out T : Any>(val data: Data<T>) : DataItem<T>() {
+    public class Leaf<out T : Any>(public val data: Data<T>) : DataItem<T>() {
         override val type: KClass<out T> get() = data.type
 
         override fun toMeta(): Meta = data.toMeta()
@@ -36,16 +36,16 @@ sealed class DataItem<out T : Any> : MetaRepr {
 /**
  * A tree-like data structure grouped into the node. All data inside the node must inherit its type
  */
-interface DataNode<out T : Any> : MetaRepr {
+public interface DataNode<out T : Any> : MetaRepr {
 
     /**
      * The minimal common ancestor to all data in the node
      */
-    val type: KClass<out T>
+    public val type: KClass<out T>
 
-    val items: Map<NameToken, DataItem<T>>
+    public val items: Map<NameToken, DataItem<T>>
 
-    val meta: Meta
+    public val meta: Meta
 
     override fun toMeta(): Meta = Meta {
         "type" put (type.simpleName ?: "undefined")
@@ -60,7 +60,7 @@ interface DataNode<out T : Any> : MetaRepr {
      * Start computation for all goals in data node and return a job for the whole node
      */
     @Suppress("DeferredResultUnused")
-    fun CoroutineScope.startAll(): Job = launch {
+    public fun CoroutineScope.startAll(): Job = launch {
         items.values.forEach {
             when (it) {
                 is DataItem.Node<*> -> it.node.run { startAll() }
@@ -69,36 +69,36 @@ interface DataNode<out T : Any> : MetaRepr {
         }
     }
 
-    companion object {
-        const val TYPE = "dataNode"
+    public companion object {
+        public const val TYPE: String = "dataNode"
 
-        operator fun <T : Any> invoke(type: KClass<out T>, block: DataTreeBuilder<T>.() -> Unit) =
+        public operator fun <T : Any> invoke(type: KClass<out T>, block: DataTreeBuilder<T>.() -> Unit): DataTree<T> =
             DataTreeBuilder(type).apply(block).build()
 
-        inline operator fun <reified T : Any> invoke(noinline block: DataTreeBuilder<T>.() -> Unit) =
+        public inline operator fun <reified T : Any> invoke(noinline block: DataTreeBuilder<T>.() -> Unit): DataTree<T> =
             DataTreeBuilder(T::class).apply(block).build()
 
-        fun <T : Any> builder(type: KClass<out T>) = DataTreeBuilder(type)
+        public fun <T : Any> builder(type: KClass<out T>): DataTreeBuilder<T> = DataTreeBuilder(type)
     }
 }
 
-suspend fun <T: Any> DataNode<T>.join(): Unit = coroutineScope { startAll().join() }
+public suspend fun <T: Any> DataNode<T>.join(): Unit = coroutineScope { startAll().join() }
 
-val <T : Any> DataItem<T>?.node: DataNode<T>? get() = (this as? DataItem.Node<T>)?.node
-val <T : Any> DataItem<T>?.data: Data<T>? get() = (this as? DataItem.Leaf<T>)?.data
+public val <T : Any> DataItem<T>?.node: DataNode<T>? get() = (this as? DataItem.Node<T>)?.node
+public val <T : Any> DataItem<T>?.data: Data<T>? get() = (this as? DataItem.Leaf<T>)?.data
 
-operator fun <T : Any> DataNode<T>.get(name: Name): DataItem<T>? = when (name.length) {
+public operator fun <T : Any> DataNode<T>.get(name: Name): DataItem<T>? = when (name.length) {
     0 -> error("Empty name")
     1 -> items[name.firstOrNull()]
     else -> get(name.firstOrNull()!!.asName()).node?.get(name.cutFirst())
 }
 
-operator fun <T : Any> DataNode<T>.get(name: String): DataItem<T>? = get(name.toName())
+public operator fun <T : Any> DataNode<T>.get(name: String): DataItem<T>? = get(name.toName())
 
 /**
  * Sequence of all children including nodes
  */
-fun <T : Any> DataNode<T>.asSequence(): Sequence<Pair<Name, DataItem<T>>> = sequence {
+public fun <T : Any> DataNode<T>.asSequence(): Sequence<Pair<Name, DataItem<T>>> = sequence {
     items.forEach { (head, item) ->
         yield(head.asName() to item)
         if (item is DataItem.Node) {
@@ -112,7 +112,7 @@ fun <T : Any> DataNode<T>.asSequence(): Sequence<Pair<Name, DataItem<T>>> = sequ
 /**
  * Sequence of data entries
  */
-fun <T : Any> DataNode<T>.dataSequence(): Sequence<Pair<Name, Data<T>>> = sequence {
+public fun <T : Any> DataNode<T>.dataSequence(): Sequence<Pair<Name, Data<T>>> = sequence {
     items.forEach { (head, item) ->
         when (item) {
             is DataItem.Leaf -> yield(head.asName() to item.data)
@@ -125,9 +125,9 @@ fun <T : Any> DataNode<T>.dataSequence(): Sequence<Pair<Name, Data<T>>> = sequen
     }
 }
 
-operator fun <T : Any> DataNode<T>.iterator(): Iterator<Pair<Name, DataItem<T>>> = asSequence().iterator()
+public operator fun <T : Any> DataNode<T>.iterator(): Iterator<Pair<Name, DataItem<T>>> = asSequence().iterator()
 
-class DataTree<out T : Any> internal constructor(
+public class DataTree<out T : Any> internal constructor(
     override val type: KClass<out T>,
     override val items: Map<NameToken, DataItem<T>>,
     override val meta: Meta
@@ -142,17 +142,17 @@ private sealed class DataTreeBuilderItem<out T : Any> {
  * A builder for a DataTree.
  */
 @DFBuilder
-class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
+public class DataTreeBuilder<T : Any>(public val type: KClass<out T>) {
     private val map = HashMap<NameToken, DataTreeBuilderItem<T>>()
 
     private var meta = MetaBuilder()
 
-    operator fun set(token: NameToken, node: DataTreeBuilder<out T>) {
+    public operator fun set(token: NameToken, node: DataTreeBuilder<out T>) {
         if (map.containsKey(token)) error("Tree entry with name $token is not empty")
         map[token] = DataTreeBuilderItem.Node(node)
     }
 
-    operator fun set(token: NameToken, data: Data<T>) {
+    public operator fun set(token: NameToken, data: Data<T>) {
         if (map.containsKey(token)) error("Tree entry with name $token is not empty")
         map[token] = DataTreeBuilderItem.Leaf(data)
     }
@@ -173,7 +173,7 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
         }
     }
 
-    operator fun set(name: Name, data: Data<T>) {
+    public operator fun set(name: Name, data: Data<T>) {
         when (name.length) {
             0 -> error("Can't add data with empty name")
             1 -> set(name.firstOrNull()!!, data)
@@ -181,7 +181,7 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
         }
     }
 
-    operator fun set(name: Name, node: DataTreeBuilder<out T>) {
+    public operator fun set(name: Name, node: DataTreeBuilder<out T>) {
         when (name.length) {
             0 -> error("Can't add data with empty name")
             1 -> set(name.firstOrNull()!!, node)
@@ -189,9 +189,9 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
         }
     }
 
-    operator fun set(name: Name, node: DataNode<T>) = set(name, node.builder())
+    public operator fun set(name: Name, node: DataNode<T>): Unit = set(name, node.builder())
 
-    operator fun set(name: Name, item: DataItem<T>) = when (item) {
+    public operator fun set(name: Name, item: DataItem<T>): Unit = when (item) {
         is DataItem.Node<T> -> set(name, item.node.builder())
         is DataItem.Leaf<T> -> set(name, item.data)
     }
@@ -199,25 +199,25 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
     /**
      * Append data to node
      */
-    infix fun String.put(data: Data<T>) = set(toName(), data)
+    public infix fun String.put(data: Data<T>): Unit = set(toName(), data)
 
     /**
      * Append node
      */
-    infix fun String.put(node: DataNode<T>) = set(toName(), node)
+    public infix fun String.put(node: DataNode<T>): Unit = set(toName(), node)
 
-    infix fun String.put(item: DataItem<T>) = set(toName(), item)
+    public infix fun String.put(item: DataItem<T>): Unit = set(toName(), item)
 
     /**
      * Build and append node
      */
-    infix fun String.put(block: DataTreeBuilder<T>.() -> Unit) = set(toName(), DataTreeBuilder(type).apply(block))
+    public infix fun String.put(block: DataTreeBuilder<T>.() -> Unit): Unit = set(toName(), DataTreeBuilder(type).apply(block))
 
 
     /**
      * Update data with given node data and meta with node meta.
      */
-    fun update(node: DataNode<T>) {
+    public fun update(node: DataNode<T>) {
         node.dataSequence().forEach {
             //TODO check if the place is occupied
             this[it.first] = it.second
@@ -225,13 +225,13 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
         meta.update(node.meta)
     }
 
-    fun meta(block: MetaBuilder.() -> Unit) = meta.apply(block)
+    public fun meta(block: MetaBuilder.() -> Unit): MetaBuilder = meta.apply(block)
 
-    fun meta(meta: Meta) {
+    public fun meta(meta: Meta) {
         this.meta = meta.builder()
     }
 
-    fun build(): DataTree<T> {
+    public fun build(): DataTree<T> {
         val resMap = map.mapValues { (_, value) ->
             when (value) {
                 is DataTreeBuilderItem.Leaf -> DataItem.Leaf(value.value)
@@ -242,50 +242,50 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
     }
 }
 
-fun <T : Any> DataTreeBuilder<T>.datum(name: Name, data: Data<T>) {
+public fun <T : Any> DataTreeBuilder<T>.datum(name: Name, data: Data<T>) {
     this[name] = data
 }
 
-fun <T : Any> DataTreeBuilder<T>.datum(name: String, data: Data<T>) {
+public fun <T : Any> DataTreeBuilder<T>.datum(name: String, data: Data<T>) {
     this[name.toName()] = data
 }
 
-fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, meta: Meta = Meta.EMPTY) {
+public fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, meta: Meta = Meta.EMPTY) {
     this[name] = Data.static(data, meta)
 }
 
-fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, block: MetaBuilder.() -> Unit = {}) {
+public fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, block: MetaBuilder.() -> Unit = {}) {
     this[name] = Data.static(data, Meta(block))
 }
 
-fun <T : Any> DataTreeBuilder<T>.static(name: String, data: T, block: MetaBuilder.() -> Unit = {}) {
+public fun <T : Any> DataTreeBuilder<T>.static(name: String, data: T, block: MetaBuilder.() -> Unit = {}) {
     this[name.toName()] = Data.static(data, Meta(block))
 }
 
-fun <T : Any> DataTreeBuilder<T>.node(name: Name, node: DataNode<T>) {
+public fun <T : Any> DataTreeBuilder<T>.node(name: Name, node: DataNode<T>) {
     this[name] = node
 }
 
-fun <T : Any> DataTreeBuilder<T>.node(name: String, node: DataNode<T>) {
+public fun <T : Any> DataTreeBuilder<T>.node(name: String, node: DataNode<T>) {
     this[name.toName()] = node
 }
 
-inline fun <reified T : Any> DataTreeBuilder<T>.node(name: Name, noinline block: DataTreeBuilder<T>.() -> Unit) {
+public inline fun <reified T : Any> DataTreeBuilder<T>.node(name: Name, noinline block: DataTreeBuilder<T>.() -> Unit) {
     this[name] = DataNode(T::class, block)
 }
 
-inline fun <reified T : Any> DataTreeBuilder<T>.node(name: String, noinline block: DataTreeBuilder<T>.() -> Unit) {
+public inline fun <reified T : Any> DataTreeBuilder<T>.node(name: String, noinline block: DataTreeBuilder<T>.() -> Unit) {
     this[name.toName()] = DataNode(T::class, block)
 }
 
 /**
  * Generate a mutable builder from this node. Node content is not changed
  */
-fun <T : Any> DataNode<T>.builder(): DataTreeBuilder<T> = DataTreeBuilder(type).apply {
+public fun <T : Any> DataNode<T>.builder(): DataTreeBuilder<T> = DataTreeBuilder(type).apply {
     dataSequence().forEach { (name, data) -> this[name] = data }
 }
 
-fun <T : Any> DataNode<T>.filter(predicate: (Name, Data<T>) -> Boolean): DataNode<T> = DataNode.invoke(type) {
+public fun <T : Any> DataNode<T>.filter(predicate: (Name, Data<T>) -> Boolean): DataNode<T> = DataNode.invoke(type) {
     dataSequence().forEach { (name, data) ->
         if (predicate(name, data)) {
             this[name] = data
@@ -293,4 +293,4 @@ fun <T : Any> DataNode<T>.filter(predicate: (Name, Data<T>) -> Boolean): DataNod
     }
 }
 
-fun <T : Any> DataNode<T>.first(): Data<T>? = dataSequence().first().second
\ No newline at end of file
+public fun <T : Any> DataNode<T>.first(): Data<T>? = dataSequence().first().second
\ No newline at end of file
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Goal.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Goal.kt
index 8c0eeec7..e5050d22 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Goal.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Goal.kt
@@ -1,37 +1,36 @@
 package hep.dataforge.data
 
+import hep.dataforge.meta.DFExperimental
 import kotlinx.coroutines.*
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.EmptyCoroutineContext
 
-interface Goal<out T> {
-    val dependencies: Collection<Goal<*>>
+public interface Goal<out T> {
+    public val dependencies: Collection<Goal<*>>
     /**
      * Returns current running coroutine if the goal is started
      */
-    val result: Deferred<T>?
+    public val result: Deferred<T>?
 
     /**
      * Get ongoing computation or start a new one.
      * Does not guarantee thread safety. In case of multi-thread access, could create orphan computations.
      */
-    fun CoroutineScope.startAsync(): Deferred<T>
+    public fun CoroutineScope.startAsync(): Deferred<T>
 
     /**
      * Reset the computation
      */
-    fun reset()
+    public fun reset()
 
-    companion object {
-
-    }
+    public companion object
 }
 
-suspend fun <T> Goal<T>.await(): T = coroutineScope { startAsync().await() }
+public suspend fun <T> Goal<T>.await(): T = coroutineScope { startAsync().await() }
 
-val Goal<*>.isComplete get() = result?.isCompleted ?: false
+public val Goal<*>.isComplete: Boolean get() = result?.isCompleted ?: false
 
-open class StaticGoal<T>(val value: T) : Goal<T> {
+public open class StaticGoal<T>(public val value: T) : Goal<T> {
     override val dependencies: Collection<Goal<*>> get() = emptyList()
     override val result: Deferred<T> = CompletableDeferred(value)
 
@@ -42,10 +41,10 @@ open class StaticGoal<T>(val value: T) : Goal<T> {
     }
 }
 
-open class DynamicGoal<T>(
-    val coroutineContext: CoroutineContext = EmptyCoroutineContext,
+public open class DynamicGoal<T>(
+    private val coroutineContext: CoroutineContext = EmptyCoroutineContext,
     override val dependencies: Collection<Goal<*>> = emptyList(),
-    val block: suspend CoroutineScope.() -> T
+    public val block: suspend CoroutineScope.() -> T
 ) : Goal<T> {
 
     final override var result: Deferred<T>? = null
@@ -55,6 +54,7 @@ open class DynamicGoal<T>(
      * Get ongoing computation or start a new one.
      * Does not guarantee thread safety. In case of multi-thread access, could create orphan computations.
      */
+    @DFExperimental
     override fun CoroutineScope.startAsync(): Deferred<T> {
         val startedDependencies = this@DynamicGoal.dependencies.map { goal ->
             goal.run { startAsync() }
@@ -82,7 +82,7 @@ open class DynamicGoal<T>(
 /**
  * Create a one-to-one goal based on existing goal
  */
-fun <T, R> Goal<T>.map(
+public fun <T, R> Goal<T>.map(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     block: suspend CoroutineScope.(T) -> R
 ): Goal<R> = DynamicGoal(coroutineContext, listOf(this)) {
@@ -92,7 +92,7 @@ fun <T, R> Goal<T>.map(
 /**
  * Create a joining goal.
  */
-fun <T, R> Collection<Goal<T>>.reduce(
+public fun <T, R> Collection<Goal<T>>.reduce(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     block: suspend CoroutineScope.(Collection<T>) -> R
 ): Goal<R> = DynamicGoal(coroutineContext, this) {
@@ -105,7 +105,7 @@ fun <T, R> Collection<Goal<T>>.reduce(
  * @param T type of the input goal
  * @param R type of the result goal
  */
-fun <K, T, R> Map<K, Goal<T>>.reduce(
+public fun <K, T, R> Map<K, Goal<T>>.reduce(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     block: suspend CoroutineScope.(Map<K, T>) -> R
 ): Goal<R> = DynamicGoal(coroutineContext, this.values) {
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/GroupRule.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/GroupRule.kt
index 5cfc55e8..0a5de778 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/GroupRule.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/GroupRule.kt
@@ -19,10 +19,10 @@ import hep.dataforge.meta.Meta
 import hep.dataforge.meta.get
 import hep.dataforge.meta.string
 
-interface GroupRule {
-    operator fun <T : Any> invoke(node: DataNode<T>): Map<String, DataNode<T>>
+public interface GroupRule {
+    public operator fun <T : Any> invoke(node: DataNode<T>): Map<String, DataNode<T>>
 
-    companion object{
+    public companion object{
         /**
          * Create grouping rule that creates groups for different values of value
          * field with name [key]
@@ -31,7 +31,7 @@ interface GroupRule {
          * @param defaultTagValue
          * @return
          */
-        fun byValue(key: String, defaultTagValue: String): GroupRule = object :
+        public fun byValue(key: String, defaultTagValue: String): GroupRule = object :
             GroupRule {
             override fun <T : Any> invoke(node: DataNode<T>): Map<String, DataNode<T>> {
                 val map = HashMap<String, DataTreeBuilder<T>>()
@@ -52,7 +52,7 @@ interface GroupRule {
 //        def = "default",
 //        info = "Default value which should be used for content in which the grouping value is not presented"
 //    )
-        fun byMeta(config: Meta): GroupRule {
+        public fun byMeta(config: Meta): GroupRule {
             //TODO expand grouping options
             return config["byValue"]?.string?.let {
                 byValue(
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/MapAction.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/MapAction.kt
index 61598349..e5504530 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/MapAction.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/MapAction.kt
@@ -7,32 +7,31 @@ import kotlin.reflect.KClass
 /**
  * Action environment includes data name, data meta and action configuration meta
  */
-data class ActionEnv(
+public data class ActionEnv(
     val name: Name,
     val meta: Meta,
     val actionMeta: Meta
 )
 
-
 /**
  * Action environment
  */
 @DFBuilder
-class MapActionBuilder<T, R>(var name: Name, var meta: MetaBuilder, val actionMeta: Meta) {
-    lateinit var result: suspend ActionEnv.(T) -> R
+public class MapActionBuilder<T, R>(public var name: Name, public var meta: MetaBuilder, public val actionMeta: Meta) {
+    public lateinit var result: suspend ActionEnv.(T) -> R
 
     /**
      * Calculate the result of goal
      */
-    fun result(f: suspend ActionEnv.(T) -> R) {
+    public fun result(f: suspend ActionEnv.(T) -> R) {
         result = f;
     }
 }
 
 
-class MapAction<T : Any, out R : Any>(
-    val inputType: KClass<T>,
-    val outputType: KClass<out R>,
+public class MapAction<T : Any, out R : Any>(
+    public val inputType: KClass<T>,
+    public val outputType: KClass<out R>,
     private val block: MapActionBuilder<T, R>.() -> Unit
 ) : Action<T, R> {
 
@@ -67,7 +66,7 @@ class MapAction<T : Any, out R : Any>(
     }
 }
 
-inline fun <reified T : Any, reified R : Any> DataNode<T>.map(
+public inline fun <reified T : Any, reified R : Any> DataNode<T>.map(
     meta: Meta,
     noinline action: MapActionBuilder<in T, out R>.() -> Unit
 ): DataNode<R> = MapAction(T::class, R::class, action).invoke(this, meta)
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/ReduceAction.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/ReduceAction.kt
index 0efb5506..a0227af9 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/ReduceAction.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/ReduceAction.kt
@@ -7,25 +7,25 @@ import hep.dataforge.names.toName
 import kotlin.reflect.KClass
 
 
-class JoinGroup<T : Any, R : Any>(var name: String, internal val node: DataNode<T>) {
+public class JoinGroup<T : Any, R : Any>(public var name: String, internal val node: DataNode<T>) {
 
-    var meta: MetaBuilder = MetaBuilder()
+    public var meta: MetaBuilder = MetaBuilder()
 
-    lateinit var result: suspend ActionEnv.(Map<Name, T>) -> R
+    public lateinit var result: suspend ActionEnv.(Map<Name, T>) -> R
 
-    fun result(f: suspend ActionEnv.(Map<Name, T>) -> R) {
+    public fun result(f: suspend ActionEnv.(Map<Name, T>) -> R) {
         this.result = f;
     }
 
 }
 
-class ReduceGroupBuilder<T : Any, R : Any>(val actionMeta: Meta) {
+public class ReduceGroupBuilder<T : Any, R : Any>(public val actionMeta: Meta) {
     private val groupRules: MutableList<(DataNode<T>) -> List<JoinGroup<T, R>>> = ArrayList();
 
     /**
      * introduce grouping by value name
      */
-    fun byValue(tag: String, defaultTag: String = "@default", action: JoinGroup<T, R>.() -> Unit) {
+    public fun byValue(tag: String, defaultTag: String = "@default", action: JoinGroup<T, R>.() -> Unit) {
         groupRules += { node ->
             GroupRule.byValue(tag, defaultTag).invoke(node).map {
                 JoinGroup<T, R>(it.key, it.value).apply(action)
@@ -36,7 +36,7 @@ class ReduceGroupBuilder<T : Any, R : Any>(val actionMeta: Meta) {
     /**
      * Add a single fixed group to grouping rules
      */
-    fun group(groupName: String, filter: DataFilter, action: JoinGroup<T, R>.() -> Unit) {
+    public fun group(groupName: String, filter: DataFilter, action: JoinGroup<T, R>.() -> Unit) {
         groupRules += { node ->
             listOf(
                 JoinGroup<T, R>(groupName, node.filter(filter)).apply(action)
@@ -44,7 +44,7 @@ class ReduceGroupBuilder<T : Any, R : Any>(val actionMeta: Meta) {
         }
     }
 
-    fun group(groupName: String, filter: (Name, Data<T>) -> Boolean, action: JoinGroup<T, R>.() -> Unit) {
+    public fun group(groupName: String, filter: (Name, Data<T>) -> Boolean, action: JoinGroup<T, R>.() -> Unit) {
         groupRules += { node ->
             listOf(
                 JoinGroup<T, R>(groupName, node.filter(filter)).apply(action)
@@ -55,7 +55,7 @@ class ReduceGroupBuilder<T : Any, R : Any>(val actionMeta: Meta) {
     /**
      * Apply transformation to the whole node
      */
-    fun result(resultName: String, f: suspend ActionEnv.(Map<Name, T>) -> R) {
+    public fun result(resultName: String, f: suspend ActionEnv.(Map<Name, T>) -> R) {
         groupRules += { node ->
             listOf(JoinGroup<T, R>(resultName, node).apply { result(f) })
         }
@@ -71,9 +71,9 @@ class ReduceGroupBuilder<T : Any, R : Any>(val actionMeta: Meta) {
 /**
  * The same rules as for KPipe
  */
-class ReduceAction<T : Any, R : Any>(
-    val inputType: KClass<T>,
-    val outputType: KClass<out R>,
+public class ReduceAction<T : Any, R : Any>(
+    public val inputType: KClass<T>,
+    public val outputType: KClass<out R>,
     private val action: ReduceGroupBuilder<T, R>.() -> Unit
 ) : Action<T, R> {
 
@@ -104,4 +104,4 @@ class ReduceAction<T : Any, R : Any>(
     }
 }
 
-operator fun <T> Map<Name, T>.get(name: String) = get(name.toName())
+public operator fun <T> Map<Name, T>.get(name: String): T? = get(name.toName())
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/SplitAction.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/SplitAction.kt
index dc29394c..731a9403 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/SplitAction.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/SplitAction.kt
@@ -10,16 +10,16 @@ import kotlin.collections.set
 import kotlin.reflect.KClass
 
 
-class FragmentRule<T : Any, R : Any>(val name: Name, var meta: MetaBuilder) {
-    lateinit var result: suspend (T) -> R
+public class FragmentRule<T : Any, R : Any>(public val name: Name, public var meta: MetaBuilder) {
+    public lateinit var result: suspend (T) -> R
 
-    fun result(f: suspend (T) -> R) {
+    public fun result(f: suspend (T) -> R) {
         result = f;
     }
 }
 
 
-class SplitBuilder<T : Any, R : Any>(val name: Name, val meta: Meta) {
+public class SplitBuilder<T : Any, R : Any>(public val name: Name, public val meta: Meta) {
     internal val fragments: MutableMap<Name, FragmentRule<T, R>.() -> Unit> = HashMap()
 
     /**
@@ -27,14 +27,14 @@ class SplitBuilder<T : Any, R : Any>(val name: Name, val meta: Meta) {
      * @param name the name of a fragment
      * @param rule the rule to transform fragment name and meta using
      */
-    fun fragment(name: String, rule: FragmentRule<T, R>.() -> Unit) {
+    public fun fragment(name: String, rule: FragmentRule<T, R>.() -> Unit) {
         fragments[name.toName()] = rule
     }
 }
 
-class SplitAction<T : Any, R : Any>(
-    val inputType: KClass<T>,
-    val outputType: KClass<out R>,
+public class SplitAction<T : Any, R : Any>(
+    public val inputType: KClass<T>,
+    public val outputType: KClass<out R>,
     private val action: SplitBuilder<T, R>.() -> Unit
 ) : Action<T, R> {
 
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt
index db8b7ab5..26563bc8 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt
@@ -6,7 +6,7 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Deferred
 import kotlin.reflect.KClass
 
-fun <R : Any, T : R> Data<T>.upcast(type: KClass<out R>): Data<R> {
+public fun <R : Any, T : R> Data<T>.upcast(type: KClass<out R>): Data<R> {
     return object : Data<R> by this {
         override val type: KClass<out R> = type
     }
@@ -15,7 +15,7 @@ fun <R : Any, T : R> Data<T>.upcast(type: KClass<out R>): Data<R> {
 /**
  * Safe upcast a [Data] to a supertype
  */
-inline fun <reified R : Any, T : R> Data<T>.upcast(): Data<R> = upcast(R::class)
+public inline fun <reified R : Any, T : R> Data<T>.upcast(): Data<R> = upcast(R::class)
 
 /**
  * Check if node could be safely cast to given class
@@ -27,7 +27,7 @@ internal expect fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean
  */
 internal expect fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean
 
-fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
+public fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
     is DataItem.Node -> node.canCast(type)
     is DataItem.Leaf -> data.canCast(type)
 }
@@ -36,7 +36,7 @@ fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
  * Unsafe cast of data node
  */
 @Suppress("UNCHECKED_CAST")
-fun <R : Any> Data<*>.cast(type: KClass<out R>): Data<R> {
+public fun <R : Any> Data<*>.cast(type: KClass<out R>): Data<R> {
     return object : Data<R> {
         override val meta: Meta get() = this@cast.meta
         override val dependencies: Collection<Goal<*>> get() = this@cast.dependencies
@@ -47,10 +47,10 @@ fun <R : Any> Data<*>.cast(type: KClass<out R>): Data<R> {
     }
 }
 
-inline fun <reified R : Any> Data<*>.cast(): Data<R> = cast(R::class)
+public inline fun <reified R : Any> Data<*>.cast(): Data<R> = cast(R::class)
 
 @Suppress("UNCHECKED_CAST")
-fun <R : Any> DataNode<*>.cast(type: KClass<out R>): DataNode<R> {
+public fun <R : Any> DataNode<*>.cast(type: KClass<out R>): DataNode<R> {
     return object : DataNode<R> {
         override val meta: Meta get() = this@cast.meta
         override val type: KClass<out R> = type
@@ -58,12 +58,12 @@ fun <R : Any> DataNode<*>.cast(type: KClass<out R>): DataNode<R> {
     }
 }
 
-inline fun <reified R : Any> DataNode<*>.cast(): DataNode<R> = cast(R::class)
+public inline fun <reified R : Any> DataNode<*>.cast(): DataNode<R> = cast(R::class)
 
 /**
  * Check that node is compatible with given type meaning that each element could be cast to the type
  */
-fun <T : Any> DataNode<*>.ensureType(type: KClass<out T>) {
+public fun <T : Any> DataNode<*>.ensureType(type: KClass<out T>) {
     if (!canCast(type)) {
         error("$type expected, but $type received")
     }
diff --git a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt
index 3590679c..b67becff 100644
--- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt
+++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt
@@ -8,7 +8,7 @@ import kotlin.reflect.KClass
 /**
  * A zero-copy data node wrapper that returns only children with appropriate type.
  */
-class TypeFilteredDataNode<out T : Any>(val origin: DataNode<*>, override val type: KClass<out T>) : DataNode<T> {
+public class TypeFilteredDataNode<out T : Any>(public val origin: DataNode<*>, override val type: KClass<out T>) : DataNode<T> {
     override val meta: Meta get() = origin.meta
     override val items: Map<NameToken, DataItem<T>> by lazy {
         origin.items.mapNotNull { (key, item) ->
diff --git a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
index ca9b0024..6f758dae 100644
--- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
+++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
@@ -39,10 +39,10 @@ public fun <R : Any> DataNode<*>.filterIsInstance(type: KClass<out R>): DataNode
 /**
  * Filter all elements of given data item that could be cast to given type. If no elements are available, return null.
  */
-fun <R : Any> DataItem<*>?.filterIsInstance(type: KClass<out R>): DataItem<R>? = when (this) {
+public fun <R : Any> DataItem<*>?.filterIsInstance(type: KClass<out R>): DataItem<R>? = when (this) {
     null -> null
     is DataItem.Node -> DataItem.Node(this.node.filterIsInstance(type))
     is DataItem.Leaf -> this.data.filterIsInstance(type)?.let { DataItem.Leaf(it) }
 }
 
-inline fun <reified R : Any> DataItem<*>?.filterIsInstance(): DataItem<R>? = this@filterIsInstance.filterIsInstance(R::class)
\ No newline at end of file
+public inline fun <reified R : Any> DataItem<*>?.filterIsInstance(): DataItem<R>? = this@filterIsInstance.filterIsInstance(R::class)
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt
index f1684ce8..f0c47609 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt
@@ -15,7 +15,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
     override val tag: PluginTag get() = Companion.tag
 
     public val ioFormatFactories: Collection<IOFormatFactory<*>> by lazy {
-        context.resolve<IOFormatFactory<*>>(IO_FORMAT_TYPE).values
+        context.gather<IOFormatFactory<*>>(IO_FORMAT_TYPE).values
     }
 
     public fun <T : Any> resolveIOFormat(item: MetaItem<*>, type: KClass<out T>): IOFormat<T>? {
@@ -30,7 +30,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
 
 
     public val metaFormatFactories: Collection<MetaFormatFactory> by lazy {
-        context.resolve<MetaFormatFactory>(META_FORMAT_TYPE).values
+        context.gather<MetaFormatFactory>(META_FORMAT_TYPE).values
     }
 
     public fun resolveMetaFormat(key: Short, meta: Meta = Meta.EMPTY): MetaFormat? =
@@ -40,7 +40,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
         metaFormatFactories.find { it.shortName == name }?.invoke(meta)
 
     public val envelopeFormatFactories: Collection<EnvelopeFormatFactory> by lazy {
-        context.resolve<EnvelopeFormatFactory>(ENVELOPE_FORMAT_TYPE).values
+        context.gather<EnvelopeFormatFactory>(ENVELOPE_FORMAT_TYPE).values
     }
 
     private fun resolveEnvelopeFormat(name: Name, meta: Meta = Meta.EMPTY): EnvelopeFormat? =
@@ -52,11 +52,11 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
         return resolveEnvelopeFormat(name.toName(), meta)
     }
 
-    override fun provideTop(target: String): Map<Name, Any> {
+    override fun content(target: String): Map<Name, Any> {
         return when (target) {
             META_FORMAT_TYPE -> defaultMetaFormats.toMap()
             ENVELOPE_FORMAT_TYPE -> defaultEnvelopeFormats.toMap()
-            else -> super.provideTop(target)
+            else -> super.content(target)
         }
     }
 
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt
index 96f42b46..5545358c 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt
@@ -17,8 +17,6 @@ public class Laminate(layers: List<Meta>) : MetaBase() {
         }
     }
 
-    public constructor(vararg layers: Meta?) : this(layers.filterNotNull())
-
     override val items: Map<NameToken, MetaItem<Meta>> by lazy {
         layers.map { it.items.keys }.flatten().associateWith { key ->
             layers.asSequence().map { it.items[key] }.filterNotNull().let(replaceRule)
@@ -80,6 +78,9 @@ public class Laminate(layers: List<Meta>) : MetaBase() {
     }
 }
 
+@Suppress("FunctionName")
+public fun Laminate(vararg layers: Meta?): Laminate = Laminate(layers.filterNotNull())
+
 /**
  * Performance optimized version of get method
  */
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
index 9a95c86d..ca78f0ae 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
@@ -51,7 +51,7 @@ public interface Value {
     override fun hashCode(): Int
 
     public companion object {
-        public const val TYPE: String = "value"
+        public const val TARGET: String = "value"
 
         /**
          * Convert object to value
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
index 063ac25d..b45a662c 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
@@ -31,7 +31,7 @@ public interface Workspace : ContextAware, Provider {
      */
     public val tasks: Map<Name, Task<*>>
 
-    override fun provideTop(target: String): Map<Name, Any> {
+    override fun content(target: String): Map<Name, Any> {
         return when (target) {
             "target", Meta.TYPE -> targets.mapKeys { it.key.toName() }
             Task.TYPE -> tasks
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
index 02452ce6..9079139d 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
@@ -13,7 +13,7 @@ public abstract class WorkspacePlugin : AbstractPlugin() {
     private val _tasks = HashSet<Task<*>>()
     public val tasks: Collection<Task<*>> get() = _tasks
 
-    override fun provideTop(target: String): Map<Name, Any> {
+    override fun content(target: String): Map<Name, Any> {
         return when (target) {
             Task.TYPE -> tasks.toMap()
             else -> emptyMap()
diff --git a/settings.gradle.kts b/settings.gradle.kts
index e3c8a08e..a76ddb02 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -8,8 +8,8 @@ pluginManagement {
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
 
-    val toolsVersion = "0.6.0-dev-4"
-    val kotlinVersion = "1.4.0"
+    val toolsVersion = "0.6.0"
+    val kotlinVersion = "1.4.10"
 
     plugins {
         id("ru.mipt.npm.mpp") version toolsVersion

From 4ab9751bea1e42755fe27ed436e1d28252685ef9 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sun, 13 Sep 2020 20:06:09 +0300
Subject: [PATCH 23/40] Commented fake overrides in Meta to work around
 KT-41765

---
 .../src/commonMain/kotlin/hep/dataforge/meta/Meta.kt  | 11 ++++++-----
 .../kotlin/hep/dataforge/workspace/SimpleWorkspace.kt |  4 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
index 73ebbe66..138ff099 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
@@ -132,11 +132,12 @@ public interface Meta : MetaRepr, ItemProvider {
 
     override fun toMeta(): Meta = seal()
 
-    override fun equals(other: Any?): Boolean
-
-    override fun hashCode(): Int
-
-    override fun toString(): String
+    //TODO to be restored on 1.4.30 after https://youtrack.jetbrains.com/issue/KT-41765 si fixed
+//    override fun equals(other: Any?): Boolean
+//
+//    override fun hashCode(): Int
+//
+//    override fun toString(): String
 
     public companion object {
         public const val TYPE: String = "meta"
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
index 4159ea30..adec8bb9 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
@@ -1,7 +1,7 @@
 package hep.dataforge.workspace
 
 import hep.dataforge.context.Context
-import hep.dataforge.context.resolve
+import hep.dataforge.context.gather
 import hep.dataforge.context.toMap
 import hep.dataforge.data.DataNode
 import hep.dataforge.meta.Meta
@@ -19,7 +19,7 @@ public class SimpleWorkspace(
 ) : Workspace {
 
     override val tasks: Map<Name, Task<*>> by lazy {
-        context.resolve<Task<*>>(Task.TYPE) + tasks.toMap()
+        context.gather<Task<*>>(Task.TYPE) + tasks.toMap()
     }
 
     public companion object {

From bc4456637ccb261ab892d0d72313f7e03393296f Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Mon, 14 Sep 2020 20:32:41 +0300
Subject: [PATCH 24/40] Native for all

---
 .gitignore                                         |  3 +--
 .../kotlin/hep/dataforge/context/Context.kt        |  4 ++--
 .../kotlin/hep/dataforge/context/Global.kt         |  6 +++++-
 .../kotlin/hep/dataforge/context/ContextTest.kt    |  7 +++++--
 dataforge-data/build.gradle.kts                    |  2 +-
 .../kotlin/hep/dataforge/data/DataFilter.kt        |  6 +++---
 .../src/jsMain/kotlin/hep/dataforge/data/dataJS.kt |  6 ++----
 .../kotlin/hep/dataforge/data/dataNative.kt        | 14 ++++++++++++++
 dataforge-io/build.gradle.kts                      |  4 ++--
 .../kotlin/hep/dataforge/io/MetaSerializerTest.kt  |  2 ++
 .../meta/transformations/MetaTransformation.kt     |  4 ++--
 dataforge-output/build.gradle.kts                  |  2 +-
 .../kotlin/hep/dataforge/output/outputNative.kt    |  6 ++++++
 dataforge-tables/build.gradle.kts                  |  2 ++
 dataforge-workspace/build.gradle.kts               |  2 ++
 .../kotlin/hep/dataforge/workspace/Task.kt         |  2 +-
 .../kotlin/hep/dataforge/workspace/TaskModel.kt    |  2 +-
 gradle.properties                                  |  7 +++++++
 18 files changed, 59 insertions(+), 22 deletions(-)
 create mode 100644 dataforge-data/src/nativeMain/kotlin/hep/dataforge/data/dataNative.kt
 create mode 100644 dataforge-output/src/nativeMain/kotlin/hep/dataforge/output/outputNative.kt
 create mode 100644 gradle.properties

diff --git a/.gitignore b/.gitignore
index 89cc712a..17a319a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,5 +6,4 @@ out/
 build/
 
 
-!gradle-wrapper.jar
-gradle.properties
\ No newline at end of file
+!gradle-wrapper.jar
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
index 640c7b5a..b675a42b 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
@@ -47,7 +47,7 @@ public open class Context(
     /**
      * A [PluginManager] for current context
      */
-    public val plugins: PluginManager by lazy { PluginManager(this) }
+    public val plugins: PluginManager = PluginManager(this)
 
     @Deprecated("To be removed in favor of immutable plugins")
     private val activators = HashSet<Any>()
@@ -92,7 +92,7 @@ public open class Context(
         }
     }
 
-    override fun content(target: String): Map<Name, Any>  = content(target,true)
+    override fun content(target: String): Map<Name, Any> = content(target, true)
 
     override val coroutineContext: CoroutineContext by lazy {
         (parent ?: Global).coroutineContext.let { parenContext ->
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
index 4666fb78..0193ca4b 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
@@ -5,10 +5,12 @@ import hep.dataforge.names.asName
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.SupervisorJob
 import kotlin.coroutines.CoroutineContext
+import kotlin.native.concurrent.ThreadLocal
 
 /**
  * A global root context. Closing [Global] terminates the framework.
  */
+@ThreadLocal
 public object Global : Context("GLOBAL".asName(), null, Meta.EMPTY) {
 
     override val coroutineContext: CoroutineContext = GlobalScope.coroutineContext + SupervisorJob()
@@ -39,6 +41,8 @@ public object Global : Context("GLOBAL".asName(), null, Meta.EMPTY) {
     }
 
     public fun context(name: String, parent: Context = this, block: ContextBuilder.() -> Unit = {}): Context =
-        ContextBuilder(parent, name).apply(block).build()
+        ContextBuilder(parent, name).apply(block).build().also {
+            contextRegistry[name] = it
+        }
 
 }
\ No newline at end of file
diff --git a/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt b/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
index ef3d1254..58647400 100644
--- a/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
+++ b/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
@@ -21,8 +21,11 @@ class ContextTest {
 
     @Test
     fun testPluginManager() {
-        Global.plugins.load(DummyPlugin())
-        val members = Global.gather<Name>("test")
+        val context = Global.context("test"){
+            plugin(DummyPlugin())
+        }
+        //Global.plugins.load(DummyPlugin())
+        val members = context.gather<Name>("test")
         assertEquals(3, members.count())
         members.forEach {
             assertEquals(it.key, it.value.appendLeft("test"))
diff --git a/dataforge-data/build.gradle.kts b/dataforge-data/build.gradle.kts
index 587f7492..b75b0a6d 100644
--- a/dataforge-data/build.gradle.kts
+++ b/dataforge-data/build.gradle.kts
@@ -1,7 +1,7 @@
 plugins {
     id("ru.mipt.npm.mpp")
     id("ru.mipt.npm.node")
-//    id("ru.mipt.npm.native")
+    id("ru.mipt.npm.native")
 }
 
 kscience{
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
index 79f790ab..51e58ac6 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
@@ -28,7 +28,7 @@ public class DataFilter : Scheme() {
 /**
  * Apply meta-based filter to given data node
  */
-fun <T : Any> DataNode<T>.filter(filter: DataFilter): DataNode<T> {
+public fun <T : Any> DataNode<T>.filter(filter: DataFilter): DataNode<T> {
     val sourceNode = filter.from?.let { get(it.toName()).node } ?: this@filter
     val regex = filter.pattern.toRegex()
     val targetNode = DataTreeBuilder(type).apply {
@@ -46,10 +46,10 @@ fun <T : Any> DataNode<T>.filter(filter: DataFilter): DataNode<T> {
 /**
  * Filter data using [DataFilter] specification
  */
-fun <T : Any> DataNode<T>.filter(filter: Meta): DataNode<T> = filter(DataFilter.wrap(filter))
+public fun <T : Any> DataNode<T>.filter(filter: Meta): DataNode<T> = filter(DataFilter.wrap(filter))
 
 /**
  * Filter data using [DataFilter] builder
  */
-fun <T : Any> DataNode<T>.filter(filterBuilder: DataFilter.() -> Unit): DataNode<T> =
+public fun <T : Any> DataNode<T>.filter(filterBuilder: DataFilter.() -> Unit): DataNode<T> =
     filter(DataFilter(filterBuilder))
\ No newline at end of file
diff --git a/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt b/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt
index afdb032e..0257b85a 100644
--- a/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt
+++ b/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt
@@ -6,11 +6,9 @@ import kotlin.reflect.KClass
  * Check that node is compatible with given type meaning that each element could be cast to the type
  */
 internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
-    //Not supported in js yet
-    return true
+    return this.type == type
 }
 
 internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
-    //Not supported in js yet
-    return true
+    return this.type == type
 }
diff --git a/dataforge-data/src/nativeMain/kotlin/hep/dataforge/data/dataNative.kt b/dataforge-data/src/nativeMain/kotlin/hep/dataforge/data/dataNative.kt
new file mode 100644
index 00000000..fe770f88
--- /dev/null
+++ b/dataforge-data/src/nativeMain/kotlin/hep/dataforge/data/dataNative.kt
@@ -0,0 +1,14 @@
+package hep.dataforge.data
+
+import kotlin.reflect.KClass
+
+/**
+ * Check that node is compatible with given type meaning that each element could be cast to the type
+ */
+internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
+    return this.type == type
+}
+
+internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
+    return this.type == type
+}
\ No newline at end of file
diff --git a/dataforge-io/build.gradle.kts b/dataforge-io/build.gradle.kts
index 6525a243..f68129af 100644
--- a/dataforge-io/build.gradle.kts
+++ b/dataforge-io/build.gradle.kts
@@ -1,7 +1,7 @@
 plugins {
     id("ru.mipt.npm.mpp")
     id("ru.mipt.npm.node")
-//    id("ru.mipt.npm.native")
+    id("ru.mipt.npm.native")
 }
 
 description = "IO module"
@@ -12,7 +12,7 @@ kscience {
     }
 }
 
-val ioVersion by rootProject.extra("0.2.0-npm-dev-10")
+val ioVersion by rootProject.extra("0.2.0-npm-dev-11")
 
 kotlin {
     sourceSets {
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
index 64fd3d02..11177e71 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
@@ -48,8 +48,10 @@ class MetaSerializerTest {
         assertEquals(name, restored)
     }
 
+    @OptIn(ExperimentalSerializationApi::class)
     @Test
     fun testMetaItemDescriptor() {
         val descriptor = MetaItem.serializer(MetaSerializer).descriptor.getElementDescriptor(0)
+        println(descriptor)
     }
 }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt
index 2c09faa5..9529b28e 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt
@@ -138,8 +138,8 @@ public inline class MetaTransformation(public val transformations: Collection<Tr
         }
     }
 
-    companion object {
-        fun make(block: MetaTransformationBuilder.() -> Unit): MetaTransformation =
+    public companion object {
+        public fun make(block: MetaTransformationBuilder.() -> Unit): MetaTransformation =
             MetaTransformationBuilder().apply(block).build()
     }
 }
diff --git a/dataforge-output/build.gradle.kts b/dataforge-output/build.gradle.kts
index 1de9ca2e..de64db60 100644
--- a/dataforge-output/build.gradle.kts
+++ b/dataforge-output/build.gradle.kts
@@ -1,7 +1,7 @@
 plugins {
     id("ru.mipt.npm.mpp")
     id("ru.mipt.npm.node")
-//    id("ru.mipt.npm.native")
+    id("ru.mipt.npm.native")
 }
 
 kotlin {
diff --git a/dataforge-output/src/nativeMain/kotlin/hep/dataforge/output/outputNative.kt b/dataforge-output/src/nativeMain/kotlin/hep/dataforge/output/outputNative.kt
new file mode 100644
index 00000000..32eb85f5
--- /dev/null
+++ b/dataforge-output/src/nativeMain/kotlin/hep/dataforge/output/outputNative.kt
@@ -0,0 +1,6 @@
+package hep.dataforge.output
+
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+
+public actual val Dispatchers.Output: CoroutineDispatcher get() = Dispatchers.Default
\ No newline at end of file
diff --git a/dataforge-tables/build.gradle.kts b/dataforge-tables/build.gradle.kts
index b181416b..de64db60 100644
--- a/dataforge-tables/build.gradle.kts
+++ b/dataforge-tables/build.gradle.kts
@@ -1,5 +1,7 @@
 plugins {
     id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.node")
+    id("ru.mipt.npm.native")
 }
 
 kotlin {
diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts
index 8abe87cd..7af72e4b 100644
--- a/dataforge-workspace/build.gradle.kts
+++ b/dataforge-workspace/build.gradle.kts
@@ -1,5 +1,7 @@
 plugins {
     id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.node")
+    id("ru.mipt.npm.native")
 }
 
 kotlin {
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt
index fbc8637d..6792adfa 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt
@@ -49,6 +49,6 @@ public interface Task<out R : Any> : Named, Described {
     public fun run(workspace: Workspace, model: TaskModel): DataNode<R>
 
     public companion object {
-        public const val TYPE = "task"
+        public const val TYPE: String = "task"
     }
 }
\ No newline at end of file
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt
index d9a558e0..5053292e 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt
@@ -46,7 +46,7 @@ public data class TaskModel(
     }
 
     public companion object {
-        public val MODEL_TARGET_KEY = "@target".asName()
+        public val MODEL_TARGET_KEY: Name = "@target".asName()
     }
 }
 
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 00000000..4bc2b611
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,7 @@
+kotlin.code.style=official
+kotlin.parallel.tasks.in.project=true
+kotlin.mpp.enableGranularSourceSetsMetadata=true
+
+org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m
+org.gradle.parallel=true
+systemProp.org.gradle.internal.publish.checksums.insecure=true
\ No newline at end of file

From 44ef4ad97fc18491c212a6da8486d34ec49e2911 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Tue, 15 Sep 2020 21:14:21 +0300
Subject: [PATCH 25/40] bump version

---
 build.gradle.kts                                           | 2 +-
 dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/build.gradle.kts b/build.gradle.kts
index 4364d684..d1aba9ef 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -5,7 +5,7 @@ plugins {
 
 apply(plugin = "org.jetbrains.dokka")
 
-val dataforgeVersion by extra("0.2.0-dev-1")
+val dataforgeVersion by extra("0.2.0-dev-2")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
index 3bf0e762..6f976898 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
@@ -214,7 +214,7 @@ public fun IOPlugin.writeEnvelopeFile(
  * Write separate meta and data files to given directory [path]
  */
 @DFExperimental
-fun IOPlugin.writeEnvelopeDirectory(
+public fun IOPlugin.writeEnvelopeDirectory(
     path: Path,
     envelope: Envelope,
     metaFormat: MetaFormatFactory = JsonMetaFormat,

From acfb070938910636f09aeb41daafd4a73673adf6 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Wed, 16 Sep 2020 15:10:43 +0300
Subject: [PATCH 26/40] New Meta serializer

---
 .../hep/dataforge/io/MetaSerializerTest.kt    |  3 +-
 .../kotlin/hep/dataforge/meta/Config.kt       |  4 +-
 .../kotlin/hep/dataforge/meta/Meta.kt         | 46 ++++-------------
 .../hep/dataforge/meta/MetaSerializer.kt      | 49 ++++++++++++++++---
 .../kotlin/hep/dataforge/values/Value.kt      |  1 -
 5 files changed, 56 insertions(+), 47 deletions(-)

diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
index 11177e71..23fef5d5 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
@@ -27,6 +27,7 @@ class MetaSerializerTest {
     @Test
     fun testMetaSerialization() {
         val string = JSON_PRETTY.encodeToString(MetaSerializer, meta)
+        println(string)
         val restored = JSON_PLAIN.decodeFromString(MetaSerializer, string)
         assertEquals(meta, restored)
     }
@@ -35,7 +36,7 @@ class MetaSerializerTest {
     @Test
     fun testCborSerialization() {
         val bytes = Cbor.encodeToByteArray(MetaSerializer, meta)
-        println(bytes.contentToString())
+        println(bytes.decodeToString())
         val restored = Cbor.decodeFromByteArray(MetaSerializer, bytes)
         assertEquals(meta, restored)
     }
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
index 89d944a7..d1691e4e 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
@@ -28,8 +28,8 @@ public interface ObservableMeta : Meta {
 /**
  * Mutable meta representing object state
  */
-@Serializable
-public class Config : AbstractMutableMeta<Config>(), ObservableMeta {
+@Serializable(Config.Companion::class)
+public class Config() : AbstractMutableMeta<Config>(), ObservableMeta {
 
     private val listeners = HashSet<MetaListener>()
 
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
index 138ff099..5c992c6b 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
@@ -4,14 +4,11 @@ import hep.dataforge.meta.Meta.Companion.VALUE_KEY
 import hep.dataforge.meta.MetaItem.NodeItem
 import hep.dataforge.meta.MetaItem.ValueItem
 import hep.dataforge.names.*
-import hep.dataforge.values.*
-import kotlinx.serialization.ExperimentalSerializationApi
-import kotlinx.serialization.KSerializer
+import hep.dataforge.values.EnumValue
+import hep.dataforge.values.Null
+import hep.dataforge.values.Value
+import hep.dataforge.values.boolean
 import kotlinx.serialization.Serializable
-import kotlinx.serialization.Serializer
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
 import kotlinx.serialization.json.Json
 
 
@@ -20,29 +17,17 @@ import kotlinx.serialization.json.Json
  * * a [ValueItem] (leaf)
  * * a [NodeItem] (node)
  */
-@Serializable
-public sealed class MetaItem<out M : Meta> {
+@Serializable(MetaItemSerializer::class)
+public sealed class MetaItem<out M : Meta>() {
 
     abstract override fun equals(other: Any?): Boolean
 
     abstract override fun hashCode(): Int
 
-    @Serializable
+    @Serializable(MetaItemSerializer::class)
     public class ValueItem(public val value: Value) : MetaItem<Nothing>() {
         override fun toString(): String = value.toString()
 
-        @OptIn(ExperimentalSerializationApi::class)
-        @Serializer(ValueItem::class)
-        public companion object : KSerializer<ValueItem> {
-            override val descriptor: SerialDescriptor get() = ValueSerializer.descriptor
-
-            override fun deserialize(decoder: Decoder): ValueItem = ValueItem(ValueSerializer.deserialize(decoder))
-
-            override fun serialize(encoder: Encoder, value: ValueItem) {
-                ValueSerializer.serialize(encoder, value.value)
-            }
-        }
-
         override fun equals(other: Any?): Boolean {
             return this.value == (other as? ValueItem)?.value
         }
@@ -52,23 +37,11 @@ public sealed class MetaItem<out M : Meta> {
         }
     }
 
-    @Serializable
-    public class NodeItem<M : Meta>(@Serializable(MetaSerializer::class) public val node: M) : MetaItem<M>() {
+    @Serializable(MetaItemSerializer::class)
+    public class NodeItem<M : Meta>(public val node: M) : MetaItem<M>() {
         //Fixing serializer for node could cause class cast problems, but it should not since Meta descendants are not serializeable
         override fun toString(): String = node.toString()
 
-        @OptIn(ExperimentalSerializationApi::class)
-        @Serializer(NodeItem::class)
-        public companion object : KSerializer<NodeItem<out Meta>> {
-            override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
-
-            override fun deserialize(decoder: Decoder): NodeItem<*> = NodeItem(MetaSerializer.deserialize(decoder))
-
-            override fun serialize(encoder: Encoder, value: NodeItem<*>) {
-                MetaSerializer.serialize(encoder, value.node)
-            }
-        }
-
         override fun equals(other: Any?): Boolean = node == (other as? NodeItem<*>)?.node
 
         override fun hashCode(): Int = node.hashCode()
@@ -112,7 +85,6 @@ public fun interface ItemProvider {
  *
  *   * Same name siblings are supported via elements with the same [Name] but different queries
  */
-@Serializable(MetaSerializer::class)
 public interface Meta : MetaRepr, ItemProvider {
     /**
      * Top level items of meta tree
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
index dba129bc..7184ae3a 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
@@ -1,17 +1,54 @@
 package hep.dataforge.meta
 
 import hep.dataforge.names.NameToken
+import hep.dataforge.values.ValueSerializer
 import kotlinx.serialization.ExperimentalSerializationApi
+import kotlinx.serialization.InternalSerializationApi
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.Serializer
 import kotlinx.serialization.builtins.MapSerializer
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
+import kotlinx.serialization.descriptors.*
+import kotlinx.serialization.encoding.*
 import kotlinx.serialization.json.JsonDecoder
 import kotlinx.serialization.json.JsonEncoder
 import kotlinx.serialization.json.JsonObject
 
+@OptIn(ExperimentalSerializationApi::class)
+public object MetaItemSerializer : KSerializer<MetaItem<*>> {
+
+    @OptIn(InternalSerializationApi::class)
+    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("hep.dataforge.meta.MetaItem") {
+        element<Boolean>("isNode")
+        element("content", buildSerialDescriptor("MetaItem.content", PolymorphicKind.SEALED))
+    }
+
+    override fun deserialize(decoder: Decoder): MetaItem<*> {
+        decoder.decodeStructure(descriptor) {
+            //Force strict serialization order
+            require(decodeElementIndex(descriptor) == 0) { "Node flag must be first item serialized" }
+            val isNode = decodeBooleanElement(descriptor, 0)
+            require(decodeElementIndex(descriptor) == 1) { "Missing MetaItem content" }
+            val item = if (isNode) {
+                decodeSerializableElement(descriptor,1, MetaSerializer).asMetaItem()
+            } else {
+                decodeSerializableElement(descriptor,1,ValueSerializer).asMetaItem()
+            }
+            require(decodeElementIndex(descriptor) == CompositeDecoder.DECODE_DONE){"Serialized MetaItem contains additional fields"}
+            return  item
+        }
+    }
+
+    override fun serialize(encoder: Encoder, value: MetaItem<*>) {
+        encoder.encodeStructure(descriptor) {
+            encodeBooleanElement(descriptor, 0, value is MetaItem.NodeItem)
+            when (value) {
+                is MetaItem.ValueItem -> encodeSerializableElement(descriptor, 1, ValueSerializer, value.value)
+                is MetaItem.NodeItem -> encodeSerializableElement(descriptor, 1, MetaSerializer, value.node)
+            }
+        }
+    }
+}
+
 /**
  * Serialized for meta
  */
@@ -19,9 +56,9 @@ import kotlinx.serialization.json.JsonObject
 @Serializer(Meta::class)
 public object MetaSerializer : KSerializer<Meta> {
 
-    private val mapSerializer = MapSerializer(
-        NameToken.serializer(),
-        MetaItem.serializer(MetaSerializer)
+    private val mapSerializer: KSerializer<Map<NameToken, MetaItem<Meta>>> = MapSerializer(
+        NameToken,
+        MetaItemSerializer//MetaItem.serializer(MetaSerializer)
     )
 
     override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
index ca78f0ae..9136d525 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
@@ -19,7 +19,6 @@ public enum class ValueType {
  *
  * Value can represent a list of value objects.
  */
-@Serializable(ValueSerializer::class)
 public interface Value {
     /**
      * Get raw value of this value

From 01c209d1d69900e906d125b588e8c4753211d971 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Mon, 28 Sep 2020 15:38:29 +0300
Subject: [PATCH 27/40] Finish migration to 1.4.20

---
 build.gradle.kts                              |  10 +-
 dataforge-context/build.gradle.kts            |   1 -
 .../dataforge/context/ClassLoaderPlugin.kt    |  12 +-
 dataforge-data/build.gradle.kts               |   1 -
 dataforge-io/build.gradle.kts                 |   1 -
 .../io/yaml/FrontMatterEnvelopeFormat.kt      |  23 ++--
 .../kotlin/hep/dataforge/io/EnvelopeFormat.kt |   7 +-
 .../hep/dataforge/io/TaggedEnvelopeFormat.kt  |  31 ++++--
 .../hep/dataforge/io/TaglessEnvelopeFormat.kt |  43 +++++---
 .../jvmMain/kotlin/hep/dataforge/io/fileIO.kt |   4 +-
 .../io/{tcp/streams.kt => streamsIO.kt}       |  10 +-
 .../hep/dataforge/io/tcp/EnvelopeClient.kt    |  67 -----------
 .../hep/dataforge/io/tcp/EnvelopeServer.kt    | 104 ------------------
 .../dataforge/io/tcp/EnvelopeServerTest.kt    |  70 ------------
 dataforge-meta/build.gradle.kts               |   9 +-
 .../kotlin/hep/dataforge/meta/DynamicMeta.kt  |   8 +-
 dataforge-output/build.gradle.kts             |   1 -
 dataforge-tables/build.gradle.kts             |   1 -
 dataforge-workspace/build.gradle.kts          |   1 -
 gradle.properties                             |   2 +
 settings.gradle.kts                           |   5 +-
 21 files changed, 102 insertions(+), 309 deletions(-)
 rename dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/{tcp/streams.kt => streamsIO.kt} (75%)
 delete mode 100644 dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
 delete mode 100644 dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
 delete mode 100644 dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt

diff --git a/build.gradle.kts b/build.gradle.kts
index d1aba9ef..3a407a3f 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,11 +1,8 @@
 plugins {
-    id("ru.mipt.npm.publish") apply false
-    id("org.jetbrains.changelog") version "0.4.0"
+    id("ru.mipt.npm.project")
 }
 
-apply(plugin = "org.jetbrains.dokka")
-
-val dataforgeVersion by extra("0.2.0-dev-2")
+val dataforgeVersion by extra("0.2.0-dev-3")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
@@ -15,6 +12,8 @@ allprojects {
     group = "hep.dataforge"
     version = dataforgeVersion
 
+    apply(plugin = "org.jetbrains.dokka")
+
     repositories {
         mavenLocal()
     }
@@ -22,5 +21,4 @@ allprojects {
 
 subprojects {
     apply(plugin = "ru.mipt.npm.publish")
-    apply(plugin = "org.jetbrains.dokka")
 }
\ No newline at end of file
diff --git a/dataforge-context/build.gradle.kts b/dataforge-context/build.gradle.kts
index c8e3e588..01a7e3bb 100644
--- a/dataforge-context/build.gradle.kts
+++ b/dataforge-context/build.gradle.kts
@@ -1,6 +1,5 @@
 plugins {
     id("ru.mipt.npm.mpp")
-    id("ru.mipt.npm.node")
     id("ru.mipt.npm.native")
 }
 
diff --git a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/ClassLoaderPlugin.kt b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/ClassLoaderPlugin.kt
index 6d401613..a1e0e6e6 100644
--- a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/ClassLoaderPlugin.kt
+++ b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/ClassLoaderPlugin.kt
@@ -19,24 +19,24 @@ import java.util.*
 import kotlin.reflect.KClass
 import kotlin.reflect.full.cast
 
-class ClassLoaderPlugin(val classLoader: ClassLoader) : AbstractPlugin() {
+public class ClassLoaderPlugin(private val classLoader: ClassLoader) : AbstractPlugin() {
     override val tag: PluginTag = PluginTag("classLoader", PluginTag.DATAFORGE_GROUP)
 
     private val serviceCache: MutableMap<Class<*>, ServiceLoader<*>> = HashMap()
 
-    fun <T : Any> services(type: KClass<T>): Sequence<T> {
+    public fun <T : Any> services(type: KClass<T>): Sequence<T> {
         return serviceCache.getOrPut(type.java) { ServiceLoader.load(type.java, classLoader) }.asSequence()
             .map { type.cast(it) }
     }
 
-    companion object {
-        val DEFAULT = ClassLoaderPlugin(Global::class.java.classLoader)
+    public companion object {
+        public val DEFAULT: ClassLoaderPlugin = ClassLoaderPlugin(Global::class.java.classLoader)
     }
 }
 
-val Context.classLoaderPlugin get() = this.plugins.get() ?: ClassLoaderPlugin.DEFAULT
+public val Context.classLoaderPlugin: ClassLoaderPlugin get() = this.plugins.get() ?: ClassLoaderPlugin.DEFAULT
 
-inline fun <reified T : Any> Context.services() = classLoaderPlugin.services(T::class)
+public inline fun <reified T : Any> Context.services(): Sequence<T> = classLoaderPlugin.services(T::class)
 
 
 //open class JVMContext(
diff --git a/dataforge-data/build.gradle.kts b/dataforge-data/build.gradle.kts
index b75b0a6d..436d9428 100644
--- a/dataforge-data/build.gradle.kts
+++ b/dataforge-data/build.gradle.kts
@@ -1,6 +1,5 @@
 plugins {
     id("ru.mipt.npm.mpp")
-    id("ru.mipt.npm.node")
     id("ru.mipt.npm.native")
 }
 
diff --git a/dataforge-io/build.gradle.kts b/dataforge-io/build.gradle.kts
index f68129af..d2e3a41a 100644
--- a/dataforge-io/build.gradle.kts
+++ b/dataforge-io/build.gradle.kts
@@ -1,6 +1,5 @@
 plugins {
     id("ru.mipt.npm.mpp")
-    id("ru.mipt.npm.node")
     id("ru.mipt.npm.native")
 }
 
diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
index 8c3a3c34..aa2537be 100644
--- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
+++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
@@ -64,14 +64,19 @@ public class FrontMatterEnvelopeFormat(
         return SimpleEnvelope(meta, data)
     }
 
-    override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
-        val metaFormat = metaFormatFactory(formatMeta, io.context)
-        writeRawString("$SEPARATOR\r\n")
-        metaFormat.run { writeObject(this@writeEnvelope, envelope.meta) }
-        writeRawString("$SEPARATOR\r\n")
+    override fun writeEnvelope(
+        output: Output,
+        envelope: Envelope,
+        metaFormatFactory: MetaFormatFactory,
+        formatMeta: Meta,
+    ) {
+        val metaFormat = metaFormatFactory(formatMeta, this@FrontMatterEnvelopeFormat.io.context)
+        output.writeRawString("${hep.dataforge.io.yaml.FrontMatterEnvelopeFormat.Companion.SEPARATOR}\r\n")
+        metaFormat.run { this.writeObject(output, envelope.meta) }
+        output.writeRawString("${hep.dataforge.io.yaml.FrontMatterEnvelopeFormat.Companion.SEPARATOR}\r\n")
         //Printing data
         envelope.data?.let { data ->
-            writeBinary(data)
+            output.writeBinary(data)
         }
     }
 
@@ -105,11 +110,13 @@ public class FrontMatterEnvelopeFormat(
         override fun readPartial(input: Input): PartialEnvelope =
             default.readPartial(input)
 
-        override fun Output.writeEnvelope(
+        override fun writeEnvelope(
+            output: Output,
             envelope: Envelope,
             metaFormatFactory: MetaFormatFactory,
             formatMeta: Meta,
-        ): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
+        ): Unit = default.writeEnvelope(output, envelope, metaFormatFactory, formatMeta)
+
 
         override fun readObject(input: Input): Envelope = default.readObject(input)
 
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt
index 683f58f0..b02052c1 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt
@@ -20,15 +20,16 @@ public interface EnvelopeFormat : IOFormat<Envelope> {
 
     public fun readPartial(input: Input): PartialEnvelope
 
-    public fun Output.writeEnvelope(
+    public fun writeEnvelope(
+        output: Output,
         envelope: Envelope,
         metaFormatFactory: MetaFormatFactory = defaultMetaFormat,
-        formatMeta: Meta = Meta.EMPTY
+        formatMeta: Meta = Meta.EMPTY,
     )
 
     override fun readObject(input: Input): Envelope
 
-    override fun writeObject(output: Output, obj: Envelope): Unit = output.writeEnvelope(obj)
+    override fun writeObject(output: Output, obj: Envelope): Unit = writeEnvelope(output, obj)
 }
 
 public fun EnvelopeFormat.read(input: Input): Envelope = readObject(input)
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
index 909ce756..389c5054 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
@@ -41,18 +41,23 @@ public class TaggedEnvelopeFormat(
         writeRawString(END_SEQUENCE)
     }
 
-    override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
-        val metaFormat = metaFormatFactory.invoke(formatMeta, io.context)
+    override fun writeEnvelope(
+        output: Output,
+        envelope: Envelope,
+        metaFormatFactory: MetaFormatFactory,
+        formatMeta: Meta,
+    ) {
+        val metaFormat = metaFormatFactory.invoke(formatMeta, this@TaggedEnvelopeFormat.io.context)
         val metaBytes = metaFormat.toBinary(envelope.meta)
         val actualSize: ULong = (envelope.data?.size ?: 0).toULong()
         val tag = Tag(metaFormatFactory.key, metaBytes.size.toUInt() + 2u, actualSize)
-        writeBinary(tag.toBinary())
-        writeBinary(metaBytes)
-        writeRawString("\r\n")
+        output.writeBinary(tag.toBinary())
+        output.writeBinary(metaBytes)
+        output.writeRawString("\r\n")
         envelope.data?.let {
-            writeBinary(it)
+            output.writeBinary(it)
         }
-        flush()
+        output.flush()
     }
 
     /**
@@ -158,11 +163,19 @@ public class TaggedEnvelopeFormat(
         override fun readPartial(input: Input): PartialEnvelope =
             default.run { readPartial(input) }
 
-        override fun Output.writeEnvelope(
+        override fun writeEnvelope(
+            output: Output,
             envelope: Envelope,
             metaFormatFactory: MetaFormatFactory,
             formatMeta: Meta,
-        ): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
+        ): Unit = default.run {
+            writeEnvelope(
+                output,
+                envelope,
+                metaFormatFactory,
+                formatMeta
+            )
+        }
 
         override fun readObject(input: Input): Envelope = default.readObject(input)
     }
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
index e0d76350..f89f9bbb 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
@@ -30,32 +30,39 @@ public class TaglessEnvelopeFormat(
         writeUtf8String("#? $key: $value;\r\n")
     }
 
-    override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
-        val metaFormat = metaFormatFactory(formatMeta, io.context)
+    override fun writeEnvelope(
+        output: Output,
+        envelope: Envelope,
+        metaFormatFactory: MetaFormatFactory,
+        formatMeta: Meta
+    ) {
+        val metaFormat = metaFormatFactory(formatMeta, this.io.context)
 
         //printing header
-        writeRawString(TAGLESS_ENVELOPE_HEADER + "\r\n")
+        output.writeRawString(TAGLESS_ENVELOPE_HEADER + "\r\n")
 
         //printing all properties
-        writeProperty(META_TYPE_PROPERTY, metaFormatFactory.shortName)
+        output.writeProperty(META_TYPE_PROPERTY,
+            metaFormatFactory.shortName)
         //TODO add optional metaFormat properties
         val actualSize: Int = envelope.data?.size ?: 0
 
-        writeProperty(DATA_LENGTH_PROPERTY, actualSize)
+        output.writeProperty(DATA_LENGTH_PROPERTY, actualSize)
 
         //Printing meta
         if (!envelope.meta.isEmpty()) {
             val metaBytes = metaFormat.toBinary(envelope.meta)
-            writeProperty(META_LENGTH_PROPERTY, metaBytes.size + 2)
-            writeUtf8String(metaStart + "\r\n")
-            writeBinary(metaBytes)
-            writeRawString("\r\n")
+            output.writeProperty(META_LENGTH_PROPERTY,
+                metaBytes.size + 2)
+            output.writeUtf8String(this.metaStart + "\r\n")
+            output.writeBinary(metaBytes)
+            output.writeRawString("\r\n")
         }
 
         //Printing data
         envelope.data?.let { data ->
-            writeUtf8String(dataStart + "\r\n")
-            writeBinary(data)
+            output.writeUtf8String(this.dataStart + "\r\n")
+            output.writeBinary(data)
         }
     }
 
@@ -169,7 +176,7 @@ public class TaglessEnvelopeFormat(
 
     public companion object : EnvelopeFormatFactory {
 
-        private val propertyPattern = "#\\?\\s*(?<key>[\\w.]*)\\s*:\\s*(?<value>[^;]*);?".toRegex()
+        private val propertyPattern = "#\\?\\s*([\\w.]*)\\s*:\\s*([^;]*);?".toRegex()
 
         public const val META_TYPE_PROPERTY: String = "metaType"
         public const val META_LENGTH_PROPERTY: String = "metaLength"
@@ -197,11 +204,19 @@ public class TaglessEnvelopeFormat(
         override fun readPartial(input: Input): PartialEnvelope =
             default.run { readPartial(input) }
 
-        override fun Output.writeEnvelope(
+        override fun writeEnvelope(
+            output: Output,
             envelope: Envelope,
             metaFormatFactory: MetaFormatFactory,
             formatMeta: Meta,
-        ): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
+        ): Unit = default.run {
+            writeEnvelope(
+                output,
+                envelope,
+                metaFormatFactory,
+                formatMeta
+            )
+        }
 
         override fun readObject(input: Input): Envelope = default.readObject(input)
 
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
index 6f976898..0e53ed89 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
@@ -204,9 +204,7 @@ public fun IOPlugin.writeEnvelopeFile(
     metaFormat: MetaFormatFactory? = null,
 ) {
     path.rewrite {
-        with(envelopeFormat) {
-            writeEnvelope(envelope, metaFormat ?: envelopeFormat.defaultMetaFormat)
-        }
+        envelopeFormat.writeEnvelope(this, envelope, metaFormat ?: envelopeFormat.defaultMetaFormat)
     }
 }
 
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/streams.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/streamsIO.kt
similarity index 75%
rename from dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/streams.kt
rename to dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/streamsIO.kt
index ec79eb22..ff392552 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/streams.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/streamsIO.kt
@@ -1,4 +1,4 @@
-package hep.dataforge.io.tcp
+package hep.dataforge.io
 
 import kotlinx.io.*
 import kotlinx.io.buffer.Buffer
@@ -30,16 +30,16 @@ private class BlockingStreamInput(val source: InputStream) : Input() {
     }
 }
 
-fun <R> InputStream.read(size: Int, block: Input.() -> R): R {
+public fun <R> InputStream.read(size: Int, block: Input.() -> R): R {
     val buffer = ByteArray(size)
     read(buffer)
     return buffer.asBinary().read(block = block)
 }
 
-fun <R> InputStream.read(block: Input.() -> R): R = asInput().block()
+public fun <R> InputStream.read(block: Input.() -> R): R = asInput().block()
 
-fun <R> InputStream.readBlocking(block: Input.() -> R): R = BlockingStreamInput(this).block()
+public fun <R> InputStream.readBlocking(block: Input.() -> R): R = BlockingStreamInput(this).block()
 
-inline fun OutputStream.write(block: Output.() -> Unit) {
+public inline fun OutputStream.write(block: Output.() -> Unit) {
     asOutput().block()
 }
\ No newline at end of file
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
deleted file mode 100644
index f52b752c..00000000
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-package hep.dataforge.io.tcp
-
-import hep.dataforge.context.Context
-import hep.dataforge.context.ContextAware
-import hep.dataforge.io.*
-import hep.dataforge.meta.Meta
-import kotlinx.coroutines.asCoroutineDispatcher
-import kotlinx.coroutines.withContext
-import java.net.Socket
-import java.util.concurrent.Executors
-import kotlin.time.ExperimentalTime
-
-@ExperimentalTime
-@Deprecated("To be replaced by flow-based client")
-public class EnvelopeClient(
-    override val context: Context,
-    public val host: String,
-    public val port: Int,
-    formatFactory: EnvelopeFormatFactory = TaggedEnvelopeFormat,
-    formatMeta: Meta = Meta.EMPTY
-) : Responder, ContextAware {
-
-    private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
-
-    private val format = formatFactory(formatMeta, context = context)
-
-//    private var socket: SocketChannel? = null
-//
-//    private fun getSocket(): Socket {
-//        val socket = socket ?: Socket(host, port).also { this.socket = it }
-//        return if (socket.isConnected) {
-//            socket
-//        } else {
-//            Socket(host, port).also { this.socket = it }
-//        }
-//    }
-
-    public suspend fun close() {
-        try {
-            respond(
-                Envelope {
-                    type = EnvelopeServer.SHUTDOWN_ENVELOPE_TYPE
-                }
-            )
-        } catch (ex: Exception) {
-            logger.error { ex }
-        }
-    }
-
-
-    @Suppress("BlockingMethodInNonBlockingContext")
-    override suspend fun respond(request: Envelope): Envelope = withContext(dispatcher) {
-        //val address = InetSocketAddress(host,port)
-        val socket = Socket(host, port)
-        val inputStream = socket.getInputStream()
-        val outputStream = socket.getOutputStream()
-        format.run {
-            outputStream.write {
-                writeObject(this, request)
-            }
-            logger.debug { "Sent request with type ${request.type} to ${socket.remoteSocketAddress}" }
-            val res = inputStream.readBlocking { readObject(this) }
-            logger.debug { "Received response with type ${res.type} from ${socket.remoteSocketAddress}" }
-            return@withContext res
-        }
-    }
-}
\ No newline at end of file
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
deleted file mode 100644
index 9a6f2b0f..00000000
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
+++ /dev/null
@@ -1,104 +0,0 @@
-package hep.dataforge.io.tcp
-
-import hep.dataforge.context.Context
-import hep.dataforge.context.ContextAware
-import hep.dataforge.io.EnvelopeFormatFactory
-import hep.dataforge.io.Responder
-import hep.dataforge.io.TaggedEnvelopeFormat
-import hep.dataforge.io.type
-import hep.dataforge.meta.Meta
-import kotlinx.coroutines.*
-import java.net.ServerSocket
-import java.net.Socket
-import kotlin.concurrent.thread
-
-@Deprecated("To be replaced by flow-based server")
-public class EnvelopeServer(
-    override val context: Context,
-    val port: Int,
-    val responder: Responder,
-    val scope: CoroutineScope,
-    formatFactory: EnvelopeFormatFactory = TaggedEnvelopeFormat,
-    formatMeta: Meta = Meta.EMPTY
-) : ContextAware {
-
-    private var job: Job? = null
-
-    private val format = formatFactory(formatMeta, context = context)
-
-    public fun start() {
-        if (job == null) {
-            logger.info { "Starting envelope server on port $port" }
-            job = scope.launch(Dispatchers.IO) {
-                val serverSocket = ServerSocket(port)
-                //TODO add handshake and format negotiation
-                while (isActive && !serverSocket.isClosed) {
-                    val socket = serverSocket.accept()
-                    logger.info { "Accepted connection from ${socket.remoteSocketAddress}" }
-                    readSocket(socket)
-                }
-            }
-        }
-    }
-
-    public fun stop() {
-        logger.info { "Stopping envelope server on port $port" }
-        job?.cancel()
-        job = null
-    }
-
-//    private fun CoroutineScope.readSocket(socket: Socket) {
-//        launch(Dispatchers.IO) {
-//            val input = socket.getInputStream().asInput()
-//            val output = socket.getOutputStream().asOutput()
-//            format.run {
-//                while (isActive && socket.isConnected) {
-//                    val request = input.readThis()
-//                    logger.debug { "Accepted request with type ${request.type} from ${socket.remoteSocketAddress}" }
-//                    if (request.type == SHUTDOWN_ENVELOPE_TYPE) {
-//                        //Echo shutdown command
-//                        logger.info { "Accepted graceful shutdown signal from ${socket.inetAddress}" }
-//                        socket.close()
-//                        cancel("Graceful connection shutdown requested by client")
-//                    }
-//                    val response = responder.respond(request)
-//                    output.writeThis(response)
-//                }
-//            }
-//        }
-//    }
-
-    private fun readSocket(socket: Socket) {
-        thread {
-            val inputStream = socket.getInputStream()
-            val outputStream = socket.getOutputStream()
-            format.run {
-                while (socket.isConnected) {
-                    val request = inputStream.readBlocking { readObject(this) }
-                    logger.debug { "Accepted request with type ${request.type} from ${socket.remoteSocketAddress}" }
-                    if (request.type == SHUTDOWN_ENVELOPE_TYPE) {
-                        //Echo shutdown command
-                        outputStream.write {
-                            writeObject(this, request)
-                        }
-                        logger.info { "Accepted graceful shutdown signal from ${socket.inetAddress}" }
-                        socket.close()
-                        return@thread
-//                        cancel("Graceful connection shutdown requested by client")
-                    }
-                    runBlocking {
-                        val response = responder.respond(request)
-                        outputStream.write {
-                            writeObject(this, response)
-                        }
-                        logger.debug { "Sent response with type ${response.type} to ${socket.remoteSocketAddress}" }
-                    }
-                }
-            }
-        }
-    }
-
-    public companion object {
-        public const val SHUTDOWN_ENVELOPE_TYPE = "@shutdown"
-    }
-}
\ No newline at end of file
diff --git a/dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt b/dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt
deleted file mode 100644
index 850136d5..00000000
--- a/dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-package hep.dataforge.io.tcp
-
-import hep.dataforge.context.Global
-import hep.dataforge.io.Envelope
-import hep.dataforge.io.Responder
-import hep.dataforge.io.TaggedEnvelopeFormat
-import hep.dataforge.io.writeToByteArray
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.runBlocking
-import kotlinx.io.writeDouble
-import org.junit.jupiter.api.AfterAll
-import org.junit.jupiter.api.BeforeAll
-import org.junit.jupiter.api.Timeout
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.time.ExperimentalTime
-
-@ExperimentalStdlibApi
-object EchoResponder : Responder {
-    override suspend fun respond(request: Envelope): Envelope {
-        val string = TaggedEnvelopeFormat().run { writeToByteArray(request).decodeToString() }
-        println("ECHO:")
-        println(string)
-        return request
-    }
-}
-
-@ExperimentalTime
-@ExperimentalStdlibApi
-class EnvelopeServerTest {
-    companion object {
-        @JvmStatic
-        val echoEnvelopeServer = EnvelopeServer(Global, 7778, EchoResponder, GlobalScope)
-
-        @BeforeAll
-        @JvmStatic
-        fun start() {
-            echoEnvelopeServer.start()
-        }
-
-        @AfterAll
-        @JvmStatic
-        fun close() {
-            echoEnvelopeServer.stop()
-        }
-    }
-
-    @Test
-    @Timeout(1)
-    fun doEchoTest() {
-        val request = Envelope {
-            type = "test.echo"
-            meta {
-                "test.value" put 22
-            }
-            data {
-                writeDouble(22.7)
-            }
-        }
-        val client = EnvelopeClient(Global, host = "localhost", port = 7778)
-        runBlocking {
-            val response = client.respond(request)
-
-
-            assertEquals(request.meta, response.meta)
-//            assertEquals(request.data?.toBytes()?.decodeToString(), response.data?.toBytes()?.decodeToString())
-            client.close()
-        }
-    }
-}
\ No newline at end of file
diff --git a/dataforge-meta/build.gradle.kts b/dataforge-meta/build.gradle.kts
index 36357552..2d4aac0c 100644
--- a/dataforge-meta/build.gradle.kts
+++ b/dataforge-meta/build.gradle.kts
@@ -1,6 +1,7 @@
+import ru.mipt.npm.gradle.KScienceVersions
+
 plugins {
     id("ru.mipt.npm.mpp")
-    id("ru.mipt.npm.node")
     id("ru.mipt.npm.native")
 }
 
@@ -8,4 +9,8 @@ kscience {
     useSerialization()
 }
 
-description = "Meta definition and basic operations on meta"
\ No newline at end of file
+description = "Meta definition and basic operations on meta"
+
+dependencies{
+    commonMainApi("org.jetbrains.kotlinx:kotlinx-serialization-json:${KScienceVersions.serializationVersion}")
+}
\ No newline at end of file
diff --git a/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt b/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt
index d131fb59..9d76b606 100644
--- a/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt
+++ b/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt
@@ -8,7 +8,7 @@ import hep.dataforge.values.isList
 
 //TODO add Meta wrapper for dynamic
 
-fun Value.toDynamic(): dynamic {
+public fun Value.toDynamic(): dynamic {
     return if (isList()) {
         list.map { it.toDynamic() }.toTypedArray().asDynamic()
     } else {
@@ -19,7 +19,7 @@ fun Value.toDynamic(): dynamic {
 /**
  * Represent or copy this [Meta] to dynamic object to be passed to JS libraries
  */
-fun Meta.toDynamic(): dynamic {
+public fun Meta.toDynamic(): dynamic {
     if (this is DynamicMeta) return this.obj
 
     fun MetaItem<*>.toDynamic(): dynamic = when (this) {
@@ -38,8 +38,8 @@ fun Meta.toDynamic(): dynamic {
     return res
 }
 
-public class DynamicMeta(public val obj: dynamic) : MetaBase() {
-    private fun keys() = js("Object.keys(this.obj)") as Array<String>
+public class DynamicMeta(internal val obj: dynamic) : MetaBase() {
+    private fun keys(): Array<String> = js("Object").keys(obj)
 
     private fun isArray(@Suppress("UNUSED_PARAMETER") obj: dynamic): Boolean =
         js("Array.isArray(obj)") as Boolean
diff --git a/dataforge-output/build.gradle.kts b/dataforge-output/build.gradle.kts
index de64db60..e88f70d1 100644
--- a/dataforge-output/build.gradle.kts
+++ b/dataforge-output/build.gradle.kts
@@ -1,6 +1,5 @@
 plugins {
     id("ru.mipt.npm.mpp")
-    id("ru.mipt.npm.node")
     id("ru.mipt.npm.native")
 }
 
diff --git a/dataforge-tables/build.gradle.kts b/dataforge-tables/build.gradle.kts
index de64db60..e88f70d1 100644
--- a/dataforge-tables/build.gradle.kts
+++ b/dataforge-tables/build.gradle.kts
@@ -1,6 +1,5 @@
 plugins {
     id("ru.mipt.npm.mpp")
-    id("ru.mipt.npm.node")
     id("ru.mipt.npm.native")
 }
 
diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts
index 7af72e4b..b621b4c2 100644
--- a/dataforge-workspace/build.gradle.kts
+++ b/dataforge-workspace/build.gradle.kts
@@ -1,6 +1,5 @@
 plugins {
     id("ru.mipt.npm.mpp")
-    id("ru.mipt.npm.node")
     id("ru.mipt.npm.native")
 }
 
diff --git a/gradle.properties b/gradle.properties
index 4bc2b611..930bba55 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,6 +1,8 @@
 kotlin.code.style=official
 kotlin.parallel.tasks.in.project=true
 kotlin.mpp.enableGranularSourceSetsMetadata=true
+kotlin.native.enableDependencyPropagation=false
+kotlin.mpp.stability.nowarn=true
 
 org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m
 org.gradle.parallel=true
diff --git a/settings.gradle.kts b/settings.gradle.kts
index b7c5529f..58592961 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -10,10 +10,11 @@ pluginManagement {
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
 
-    val toolsVersion = "0.6.0-dev-5"
-    val kotlinVersion = "1.4.20-dev-3898-14"
+    val toolsVersion = "0.6.1-dev-1.4.20-M1"
+    val kotlinVersion = "1.4.20-M1"
 
     plugins {
+        id("ru.mipt.npm.project") version toolsVersion
         id("ru.mipt.npm.mpp") version toolsVersion
         id("ru.mipt.npm.jvm") version toolsVersion
         id("ru.mipt.npm.js") version toolsVersion

From ccb11b52c8c3f92b81d170810e404520df8bfee3 Mon Sep 17 00:00:00 2001
From: Mikhail Zelenyi <mihail.zelenyy@phystech.edu>
Date: Tue, 13 Oct 2020 07:59:57 +0300
Subject: [PATCH 28/40] Update Scheme.kt

Add default empty block.
---
 .../src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt        | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
index 07709ab0..913f5a3d 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
@@ -91,5 +91,5 @@ public open class MetaScheme(
 
 public fun Meta.asScheme(): MetaScheme = MetaScheme(this)
 
-public fun <T : Configurable> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit): T =
-    spec.wrap(this).apply(block)
\ No newline at end of file
+public fun <T : Configurable> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit = {}): T =
+    spec.wrap(this).apply(block)

From d6ed5f94e4994912eedf8cf687db7d4b9159dd10 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Sat, 17 Oct 2020 17:22:34 +0300
Subject: [PATCH 29/40] Removed IO dependency from Output

---
 CHANGELOG.md                                   |  1 +
 build.gradle.kts                               |  2 +-
 .../dataforge/names/NameSerializationTest.kt   | 18 ++++++++++++++++++
 dataforge-output/build.gradle.kts              |  2 +-
 .../hep/dataforge/output/TextRenderer.kt       | 10 ++++------
 dataforge-workspace/build.gradle.kts           |  1 +
 6 files changed, 26 insertions(+), 8 deletions(-)
 create mode 100644 dataforge-meta/src/commonTest/kotlin/hep/dataforge/names/NameSerializationTest.kt

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 35d67eee..baec4747 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@
 - Empty query in Name is null instead of ""
 - Provider provides an empty map instead of error by default
 - Hidden delegates hierarchy in favor of stdlib properties
+- Removed io depdendency from `dataforge-output`. Replaced Output by Appendable.
 
 ### Deprecated
 - Context activation API
diff --git a/build.gradle.kts b/build.gradle.kts
index 3a407a3f..dde77dcf 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -12,7 +12,7 @@ allprojects {
     group = "hep.dataforge"
     version = dataforgeVersion
 
-    apply(plugin = "org.jetbrains.dokka")
+    apply<org.jetbrains.dokka.gradle.DokkaPlugin>()
 
     repositories {
         mavenLocal()
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/names/NameSerializationTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/names/NameSerializationTest.kt
new file mode 100644
index 00000000..7449be2f
--- /dev/null
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/names/NameSerializationTest.kt
@@ -0,0 +1,18 @@
+package hep.dataforge.names
+
+import kotlinx.serialization.json.Json
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+
+class NameSerializationTest {
+
+    @Test
+    fun testNameSerialization() {
+        val name = "aaa.bbb.ccc".toName()
+        val json = Json.encodeToJsonElement(Name.serializer(), name)
+        println(json)
+        val reconstructed = Json.decodeFromJsonElement(Name.serializer(), json)
+        assertEquals(name, reconstructed)
+    }
+}
\ No newline at end of file
diff --git a/dataforge-output/build.gradle.kts b/dataforge-output/build.gradle.kts
index e88f70d1..6051cb1c 100644
--- a/dataforge-output/build.gradle.kts
+++ b/dataforge-output/build.gradle.kts
@@ -8,7 +8,7 @@ kotlin {
         val commonMain by getting{
             dependencies {
                 api(project(":dataforge-context"))
-                api(project(":dataforge-io"))
+                //api(project(":dataforge-io"))
             }
         }
     }
diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
index b70030e4..9249de41 100644
--- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
+++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
@@ -7,8 +7,6 @@ import hep.dataforge.provider.Type
 import hep.dataforge.provider.top
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
-import kotlinx.io.Output
-import kotlinx.io.text.writeUtf8String
 import kotlin.reflect.KClass
 
 
@@ -26,7 +24,7 @@ public interface TextFormat {
      */
     public val type: KClass<*>
 
-    public suspend fun Output.render(obj: Any)
+    public suspend fun Appendable.render(obj: Any)
 
     public companion object {
         public const val TEXT_RENDERER_TYPE: String = "dataforge.textRenderer"
@@ -37,15 +35,15 @@ public object DefaultTextFormat : TextFormat {
     override val priority: Int = Int.MAX_VALUE
     override val type: KClass<*> = Any::class
 
-    override suspend fun Output.render(obj: Any) {
-        writeUtf8String(obj.toString() + "\n")
+    override suspend fun Appendable.render(obj: Any) {
+        append(obj.toString() + "\n")
     }
 }
 
 /**
  * A text-based renderer
  */
-public class TextRenderer(override val context: Context, private val output: Output) : Renderer<Any> {
+public class TextRenderer(override val context: Context, private val output: Appendable) : Renderer<Any> {
     private val cache = HashMap<KClass<*>, TextFormat>()
 
     /**
diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts
index b621b4c2..a18ddba6 100644
--- a/dataforge-workspace/build.gradle.kts
+++ b/dataforge-workspace/build.gradle.kts
@@ -10,6 +10,7 @@ kotlin {
                 api(project(":dataforge-context"))
                 api(project(":dataforge-data"))
                 api(project(":dataforge-output"))
+                api(project(":dataforge-io"))
             }
         }
     }

From 8ef0b2247c51e00db3f0fd4537de61e083266907 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Wed, 28 Oct 2020 13:01:29 +0300
Subject: [PATCH 30/40] Changed kotlin version to 1.4.20-M2

---
 build.gradle.kts                              |    2 +-
 dataforge-context/api/dataforge-context.api   |  307 +++++
 dataforge-data/api/dataforge-data.api         |  401 +++++++
 dataforge-io/api/dataforge-io.api             |  469 ++++++++
 .../api/dataforge-io-yaml.api                 |   59 +
 dataforge-meta/api/dataforge-meta.api         | 1016 +++++++++++++++++
 dataforge-output/api/dataforge-output.api     |   68 ++
 .../api/dataforge-output-html.api             |   26 +
 .../api/dataforge-scripting.api               |    6 +
 dataforge-tables/api/dataforge-tables.api     |  302 +++++
 .../api/dataforge-workspace.api               |  273 +++++
 settings.gradle.kts                           |    4 +-
 12 files changed, 2930 insertions(+), 3 deletions(-)
 create mode 100644 dataforge-context/api/dataforge-context.api
 create mode 100644 dataforge-data/api/dataforge-data.api
 create mode 100644 dataforge-io/api/dataforge-io.api
 create mode 100644 dataforge-io/dataforge-io-yaml/api/dataforge-io-yaml.api
 create mode 100644 dataforge-meta/api/dataforge-meta.api
 create mode 100644 dataforge-output/api/dataforge-output.api
 create mode 100644 dataforge-output/dataforge-output-html/api/dataforge-output-html.api
 create mode 100644 dataforge-scripting/api/dataforge-scripting.api
 create mode 100644 dataforge-tables/api/dataforge-tables.api
 create mode 100644 dataforge-workspace/api/dataforge-workspace.api

diff --git a/build.gradle.kts b/build.gradle.kts
index dde77dcf..0c2a30ab 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,7 +2,7 @@ plugins {
     id("ru.mipt.npm.project")
 }
 
-val dataforgeVersion by extra("0.2.0-dev-3")
+val dataforgeVersion by extra("0.2.0-dev-4")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/dataforge-context/api/dataforge-context.api b/dataforge-context/api/dataforge-context.api
new file mode 100644
index 00000000..5443d3b3
--- /dev/null
+++ b/dataforge-context/api/dataforge-context.api
@@ -0,0 +1,307 @@
+public abstract class hep/dataforge/context/AbstractPlugin : hep/dataforge/context/Plugin {
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun attach (Lhep/dataforge/context/Context;)V
+	public fun content (Ljava/lang/String;)Ljava/util/Map;
+	public synthetic fun dependsOn ()Ljava/util/Collection;
+	public final fun dependsOn ()Ljava/util/List;
+	public fun detach ()V
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getDefaultChainTarget ()Ljava/lang/String;
+	public fun getDefaultTarget ()Ljava/lang/String;
+	public fun getLogger ()Lmu/KLogger;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Lhep/dataforge/names/Name;
+	protected final fun require (Lhep/dataforge/context/PluginFactory;)Lkotlin/properties/ReadOnlyProperty;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/context/AbstractPluginKt {
+	public static final fun toMap (Ljava/util/Collection;)Ljava/util/Map;
+}
+
+public final class hep/dataforge/context/ClassLoaderPlugin : hep/dataforge/context/AbstractPlugin {
+	public static final field Companion Lhep/dataforge/context/ClassLoaderPlugin$Companion;
+	public fun <init> (Ljava/lang/ClassLoader;)V
+	public fun getTag ()Lhep/dataforge/context/PluginTag;
+	public final fun services (Lkotlin/reflect/KClass;)Lkotlin/sequences/Sequence;
+}
+
+public final class hep/dataforge/context/ClassLoaderPlugin$Companion {
+	public final fun getDEFAULT ()Lhep/dataforge/context/ClassLoaderPlugin;
+}
+
+public final class hep/dataforge/context/ClassLoaderPluginKt {
+	public static final fun getClassLoaderPlugin (Lhep/dataforge/context/Context;)Lhep/dataforge/context/ClassLoaderPlugin;
+}
+
+public class hep/dataforge/context/Context : hep/dataforge/context/Named, hep/dataforge/meta/MetaRepr, hep/dataforge/provider/Provider, kotlinx/coroutines/CoroutineScope {
+	public static final field Companion Lhep/dataforge/context/Context$Companion;
+	public static final field PROPERTY_TARGET Ljava/lang/String;
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;)V
+	public final fun activate (Ljava/lang/Object;)V
+	public fun close ()V
+	public fun content (Ljava/lang/String;)Ljava/util/Map;
+	public final fun content (Ljava/lang/String;Z)Ljava/util/Map;
+	public final fun deactivate (Ljava/lang/Object;)V
+	public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
+	public fun getDefaultChainTarget ()Ljava/lang/String;
+	public fun getDefaultTarget ()Ljava/lang/String;
+	public final fun getLogger ()Lmu/KLogger;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getParent ()Lhep/dataforge/context/Context;
+	public final fun getPlugins ()Lhep/dataforge/context/PluginManager;
+	public final fun isActive ()Z
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/context/Context$Companion {
+}
+
+public abstract interface class hep/dataforge/context/ContextAware {
+	public abstract fun getContext ()Lhep/dataforge/context/Context;
+	public abstract fun getLogger ()Lmu/KLogger;
+}
+
+public final class hep/dataforge/context/ContextAware$DefaultImpls {
+	public static fun getLogger (Lhep/dataforge/context/ContextAware;)Lmu/KLogger;
+}
+
+public final class hep/dataforge/context/ContextBuilder {
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/context/Context;Ljava/lang/String;)V
+	public synthetic fun <init> (Lhep/dataforge/context/Context;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun build ()Lhep/dataforge/context/Context;
+	public final fun getName ()Ljava/lang/String;
+	public final fun plugin (Lhep/dataforge/context/Plugin;)V
+	public final fun plugin (Lhep/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;)V
+	public final fun plugin (Lhep/dataforge/context/PluginTag;Lkotlin/jvm/functions/Function1;)V
+	public final fun plugin (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public static synthetic fun plugin$default (Lhep/dataforge/context/ContextBuilder;Lhep/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public static synthetic fun plugin$default (Lhep/dataforge/context/ContextBuilder;Lhep/dataforge/context/PluginTag;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public static synthetic fun plugin$default (Lhep/dataforge/context/ContextBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public final fun properties (Lkotlin/jvm/functions/Function1;)V
+	public final fun setName (Ljava/lang/String;)V
+}
+
+public abstract interface class hep/dataforge/context/Factory {
+	public abstract fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/context/Factory$DefaultImpls {
+	public static synthetic fun invoke$default (Lhep/dataforge/context/Factory;Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;ILjava/lang/Object;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/context/Global : hep/dataforge/context/Context {
+	public static final field INSTANCE Lhep/dataforge/context/Global;
+	public fun close ()V
+	public final fun context (Ljava/lang/String;Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Context;
+	public static synthetic fun context$default (Lhep/dataforge/context/Global;Ljava/lang/String;Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/context/Context;
+	public final fun getContext (Ljava/lang/String;)Lhep/dataforge/context/Context;
+	public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
+}
+
+public abstract interface class hep/dataforge/context/Named {
+	public static final field Companion Lhep/dataforge/context/Named$Companion;
+	public abstract fun getName ()Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/context/Named$Companion {
+	public final fun nameOf (Ljava/lang/Object;)Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/context/NamedKt {
+	public static final fun isAnonymous (Lhep/dataforge/context/Named;)Z
+}
+
+public abstract interface class hep/dataforge/context/Plugin : hep/dataforge/context/ContextAware, hep/dataforge/context/Named, hep/dataforge/meta/MetaRepr, hep/dataforge/provider/Provider {
+	public static final field Companion Lhep/dataforge/context/Plugin$Companion;
+	public static final field TARGET Ljava/lang/String;
+	public abstract fun attach (Lhep/dataforge/context/Context;)V
+	public abstract fun dependsOn ()Ljava/util/Collection;
+	public abstract fun detach ()V
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getName ()Lhep/dataforge/names/Name;
+	public abstract fun getTag ()Lhep/dataforge/context/PluginTag;
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/context/Plugin$Companion {
+	public static final field TARGET Ljava/lang/String;
+}
+
+public final class hep/dataforge/context/Plugin$DefaultImpls {
+	public static fun content (Lhep/dataforge/context/Plugin;Ljava/lang/String;)Ljava/util/Map;
+	public static fun getDefaultChainTarget (Lhep/dataforge/context/Plugin;)Ljava/lang/String;
+	public static fun getDefaultTarget (Lhep/dataforge/context/Plugin;)Ljava/lang/String;
+	public static fun getLogger (Lhep/dataforge/context/Plugin;)Lmu/KLogger;
+	public static fun getName (Lhep/dataforge/context/Plugin;)Lhep/dataforge/names/Name;
+	public static fun toMeta (Lhep/dataforge/context/Plugin;)Lhep/dataforge/meta/Meta;
+}
+
+public abstract interface class hep/dataforge/context/PluginFactory : hep/dataforge/context/Factory {
+	public static final field Companion Lhep/dataforge/context/PluginFactory$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public abstract fun getTag ()Lhep/dataforge/context/PluginTag;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/context/PluginFactory$Companion {
+	public static final field TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/context/PluginManager : hep/dataforge/context/ContextAware, java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
+	public fun <init> (Lhep/dataforge/context/Context;)V
+	public final fun fetch (Lhep/dataforge/context/PluginFactory;ZLhep/dataforge/meta/Meta;)Lhep/dataforge/context/Plugin;
+	public final fun fetch (Lhep/dataforge/context/PluginFactory;ZLkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Plugin;
+	public static synthetic fun fetch$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;ZLhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
+	public static synthetic fun fetch$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
+	public final fun find (ZLkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Plugin;
+	public static synthetic fun find$default (Lhep/dataforge/context/PluginManager;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
+	public final fun get (Lhep/dataforge/context/PluginTag;Z)Lhep/dataforge/context/Plugin;
+	public final fun get (Lkotlin/reflect/KClass;Lhep/dataforge/context/PluginTag;Z)Ljava/lang/Object;
+	public static synthetic fun get$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginTag;ZILjava/lang/Object;)Lhep/dataforge/context/Plugin;
+	public static synthetic fun get$default (Lhep/dataforge/context/PluginManager;Lkotlin/reflect/KClass;Lhep/dataforge/context/PluginTag;ZILjava/lang/Object;)Ljava/lang/Object;
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getLogger ()Lmu/KLogger;
+	public fun iterator ()Ljava/util/Iterator;
+	public final fun list (Z)Ljava/util/Collection;
+	public final fun load (Lhep/dataforge/context/Plugin;)Lhep/dataforge/context/Plugin;
+	public final fun load (Lhep/dataforge/context/PluginFactory;Lhep/dataforge/meta/Meta;)Lhep/dataforge/context/Plugin;
+	public final fun load (Lhep/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Plugin;
+	public static synthetic fun load$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
+	public final fun remove (Lhep/dataforge/context/Plugin;)V
+}
+
+public final class hep/dataforge/context/PluginTag : hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/context/PluginTag$Companion;
+	public static final field DATAFORGE_GROUP Ljava/lang/String;
+	public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+	public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Ljava/lang/String;
+	public final fun component3 ()Ljava/lang/String;
+	public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lhep/dataforge/context/PluginTag;
+	public static synthetic fun copy$default (Lhep/dataforge/context/PluginTag;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lhep/dataforge/context/PluginTag;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getGroup ()Ljava/lang/String;
+	public final fun getName ()Ljava/lang/String;
+	public final fun getVersion ()Ljava/lang/String;
+	public fun hashCode ()I
+	public final fun matches (Lhep/dataforge/context/PluginTag;)Z
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/context/PluginTag$Companion {
+	public final fun fromString (Ljava/lang/String;)Lhep/dataforge/context/PluginTag;
+}
+
+public final class hep/dataforge/context/ResolveKt {
+	public static final fun gather (Lhep/dataforge/context/Context;Ljava/lang/String;Lkotlin/reflect/KClass;Z)Ljava/util/Map;
+	public static synthetic fun gather$default (Lhep/dataforge/context/Context;Ljava/lang/String;Lkotlin/reflect/KClass;ZILjava/lang/Object;)Ljava/util/Map;
+	public static final fun gatherInSequence (Lhep/dataforge/context/Context;Ljava/lang/String;Lkotlin/reflect/KClass;Z)Lkotlin/sequences/Sequence;
+	public static synthetic fun gatherInSequence$default (Lhep/dataforge/context/Context;Ljava/lang/String;Lkotlin/reflect/KClass;ZILjava/lang/Object;)Lkotlin/sequences/Sequence;
+	public static final fun getValues (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
+	public static final fun resolve (Lhep/dataforge/context/Context;Ljava/lang/String;Lhep/dataforge/names/Name;Lkotlin/reflect/KClass;)Ljava/lang/Object;
+}
+
+public abstract interface annotation class hep/dataforge/descriptors/Attribute : java/lang/annotation/Annotation {
+	public abstract fun key ()Ljava/lang/String;
+	public abstract fun value ()Ljava/lang/String;
+}
+
+public abstract interface annotation class hep/dataforge/descriptors/Attributes : java/lang/annotation/Annotation {
+	public abstract fun attrs ()[Lhep/dataforge/descriptors/Attribute;
+}
+
+public abstract interface annotation class hep/dataforge/descriptors/ItemDef : java/lang/annotation/Annotation {
+	public abstract fun info ()Ljava/lang/String;
+	public abstract fun multiple ()Z
+	public abstract fun required ()Z
+}
+
+public abstract interface annotation class hep/dataforge/descriptors/ValueDef : java/lang/annotation/Annotation {
+	public abstract fun allowed ()[Ljava/lang/String;
+	public abstract fun def ()Ljava/lang/String;
+	public abstract fun enumeration ()Ljava/lang/Class;
+	public abstract fun type ()[Lhep/dataforge/values/ValueType;
+}
+
+public final class hep/dataforge/provider/DfTypeKt {
+	public static final fun getDfType (Lkotlin/reflect/KClass;)Ljava/lang/String;
+}
+
+public final class hep/dataforge/provider/Path : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
+	public static final field Companion Lhep/dataforge/provider/Path$Companion;
+	public static final field PATH_SEGMENT_SEPARATOR Ljava/lang/String;
+	public static final synthetic fun box-impl (Ljava/util/List;)Lhep/dataforge/provider/Path;
+	public static fun constructor-impl (Ljava/util/List;)Ljava/util/List;
+	public fun equals (Ljava/lang/Object;)Z
+	public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z
+	public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z
+	public static final fun getHead-impl (Ljava/util/List;)Lhep/dataforge/provider/PathToken;
+	public static final fun getLength-impl (Ljava/util/List;)I
+	public static final fun getTail-e2ET3QM (Ljava/util/List;)Ljava/util/List;
+	public final fun getTokens ()Ljava/util/List;
+	public fun hashCode ()I
+	public static fun hashCode-impl (Ljava/util/List;)I
+	public fun iterator ()Ljava/util/Iterator;
+	public static fun iterator-impl (Ljava/util/List;)Ljava/util/Iterator;
+	public fun toString ()Ljava/lang/String;
+	public static fun toString-impl (Ljava/util/List;)Ljava/lang/String;
+	public final synthetic fun unbox-impl ()Ljava/util/List;
+}
+
+public final class hep/dataforge/provider/Path$Companion {
+	public final fun parse-IN54j3k (Ljava/lang/String;)Ljava/util/List;
+}
+
+public final class hep/dataforge/provider/PathKt {
+	public static final fun plus-MQiGgVU (Ljava/util/List;Ljava/util/List;)Ljava/util/List;
+	public static final fun toPath (Lhep/dataforge/provider/PathToken;)Ljava/util/List;
+}
+
+public final class hep/dataforge/provider/PathToken {
+	public static final field Companion Lhep/dataforge/provider/PathToken$Companion;
+	public static final field TARGET_SEPARATOR Ljava/lang/String;
+	public fun <init> (Lhep/dataforge/names/Name;Ljava/lang/String;)V
+	public synthetic fun <init> (Lhep/dataforge/names/Name;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Lhep/dataforge/names/Name;
+	public final fun component2 ()Ljava/lang/String;
+	public final fun copy (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/provider/PathToken;
+	public static synthetic fun copy$default (Lhep/dataforge/provider/PathToken;Lhep/dataforge/names/Name;Ljava/lang/String;ILjava/lang/Object;)Lhep/dataforge/provider/PathToken;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getTarget ()Ljava/lang/String;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/provider/PathToken$Companion {
+	public final fun parse (Ljava/lang/String;)Lhep/dataforge/provider/PathToken;
+}
+
+public abstract interface class hep/dataforge/provider/Provider {
+	public abstract fun content (Ljava/lang/String;)Ljava/util/Map;
+	public abstract fun getDefaultChainTarget ()Ljava/lang/String;
+	public abstract fun getDefaultTarget ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/provider/Provider$DefaultImpls {
+	public static fun content (Lhep/dataforge/provider/Provider;Ljava/lang/String;)Ljava/util/Map;
+	public static fun getDefaultChainTarget (Lhep/dataforge/provider/Provider;)Ljava/lang/String;
+	public static fun getDefaultTarget (Lhep/dataforge/provider/Provider;)Ljava/lang/String;
+}
+
+public final class hep/dataforge/provider/ProviderKt {
+	public static final fun provide-0Dbucg0 (Lhep/dataforge/provider/Provider;Ljava/util/List;Ljava/lang/String;)Ljava/lang/Object;
+	public static synthetic fun provide-0Dbucg0$default (Lhep/dataforge/provider/Provider;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/Object;
+	public static final fun top (Lhep/dataforge/provider/Provider;Ljava/lang/String;Lkotlin/reflect/KClass;)Ljava/util/Map;
+}
+
+public abstract interface annotation class hep/dataforge/provider/Type : java/lang/annotation/Annotation {
+	public abstract fun id ()Ljava/lang/String;
+}
+
diff --git a/dataforge-data/api/dataforge-data.api b/dataforge-data/api/dataforge-data.api
new file mode 100644
index 00000000..60392496
--- /dev/null
+++ b/dataforge-data/api/dataforge-data.api
@@ -0,0 +1,401 @@
+public abstract interface class hep/dataforge/data/Action {
+	public abstract fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public abstract fun isTerminal ()Z
+}
+
+public final class hep/dataforge/data/Action$DefaultImpls {
+	public static fun isTerminal (Lhep/dataforge/data/Action;)Z
+}
+
+public final class hep/dataforge/data/ActionEnv {
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Meta;)V
+	public final fun component1 ()Lhep/dataforge/names/Name;
+	public final fun component2 ()Lhep/dataforge/meta/Meta;
+	public final fun component3 ()Lhep/dataforge/meta/Meta;
+	public final fun copy (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/ActionEnv;
+	public static synthetic fun copy$default (Lhep/dataforge/data/ActionEnv;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/data/ActionEnv;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getActionMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/data/ActionKt {
+	public static final fun then (Lhep/dataforge/data/Action;Lhep/dataforge/data/Action;)Lhep/dataforge/data/Action;
+}
+
+public final class hep/dataforge/data/CoroutineMonitor : kotlin/coroutines/CoroutineContext$Element {
+	public static final field Companion Lhep/dataforge/data/CoroutineMonitor$Companion;
+	public fun <init> ()V
+	public final fun finish ()V
+	public fun fold (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
+	public fun get (Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
+	public fun getKey ()Lkotlin/coroutines/CoroutineContext$Key;
+	public final fun getStatus ()Ljava/lang/String;
+	public final fun getTotalWork ()D
+	public final fun getWorkDone ()D
+	public fun minusKey (Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
+	public fun plus (Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
+	public final fun setStatus (Ljava/lang/String;)V
+	public final fun setTotalWork (D)V
+	public final fun setWorkDone (D)V
+	public final fun start ()V
+}
+
+public final class hep/dataforge/data/CoroutineMonitor$Companion : kotlin/coroutines/CoroutineContext$Key {
+}
+
+public final class hep/dataforge/data/CoroutineMonitorKt {
+	public static final fun getDependencies (Lkotlinx/coroutines/Job;)Ljava/util/Collection;
+	public static final fun getMonitor (Lkotlin/coroutines/CoroutineContext;)Lhep/dataforge/data/CoroutineMonitor;
+	public static final fun getMonitor (Lkotlinx/coroutines/CoroutineScope;)Lhep/dataforge/data/CoroutineMonitor;
+	public static final fun getProgress (Lkotlinx/coroutines/Job;)D
+	public static final fun getStatus (Lkotlinx/coroutines/Job;)Ljava/lang/String;
+	public static final fun getTotalWork (Lkotlinx/coroutines/Job;)D
+	public static final fun getWorkDone (Lkotlinx/coroutines/Job;)D
+}
+
+public abstract interface class hep/dataforge/data/Data : hep/dataforge/data/Goal, hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/data/Data$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/Data$Companion {
+	public static final field TYPE Ljava/lang/String;
+	public final fun invoke (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/Data;
+	public final fun invoke (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/Data;
+	public static synthetic fun invoke$default (Lhep/dataforge/data/Data$Companion;Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lhep/dataforge/data/Data;
+	public static synthetic fun invoke$default (Lhep/dataforge/data/Data$Companion;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lhep/dataforge/data/Data;
+	public final fun static (Ljava/lang/Object;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/Data;
+	public static synthetic fun static$default (Lhep/dataforge/data/Data$Companion;Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/data/Data;
+}
+
+public final class hep/dataforge/data/Data$DefaultImpls {
+	public static fun toMeta (Lhep/dataforge/data/Data;)Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataCastKt {
+	public static final fun canCast (Lhep/dataforge/data/DataItem;Lkotlin/reflect/KClass;)Z
+	public static final fun cast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
+	public static final fun cast (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataNode;
+	public static final fun ensureType (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)V
+	public static final fun upcast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
+}
+
+public final class hep/dataforge/data/DataFilter : hep/dataforge/meta/Scheme {
+	public static final field Companion Lhep/dataforge/data/DataFilter$Companion;
+	public fun <init> ()V
+	public final fun getFrom ()Ljava/lang/String;
+	public final fun getPattern ()Ljava/lang/String;
+	public final fun getTo ()Ljava/lang/String;
+	public final fun isEmpty ()Z
+	public final fun setFrom (Ljava/lang/String;)V
+	public final fun setPattern (Ljava/lang/String;)V
+	public final fun setTo (Ljava/lang/String;)V
+}
+
+public final class hep/dataforge/data/DataFilter$Companion : hep/dataforge/meta/SchemeSpec {
+}
+
+public final class hep/dataforge/data/DataFilterKt {
+	public static final fun filter (Lhep/dataforge/data/DataNode;Lhep/dataforge/data/DataFilter;)Lhep/dataforge/data/DataNode;
+	public static final fun filter (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public static final fun filter (Lhep/dataforge/data/DataNode;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataNode;
+}
+
+public abstract class hep/dataforge/data/DataItem : hep/dataforge/meta/MetaRepr {
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/data/DataItem$Leaf : hep/dataforge/data/DataItem {
+	public fun <init> (Lhep/dataforge/data/Data;)V
+	public final fun getData ()Lhep/dataforge/data/Data;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataItem$Node : hep/dataforge/data/DataItem {
+	public fun <init> (Lhep/dataforge/data/DataNode;)V
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getNode ()Lhep/dataforge/data/DataNode;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataJVMKt {
+	public static final fun filterIsInstance (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
+	public static final fun filterIsInstance (Lhep/dataforge/data/DataItem;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataItem;
+	public static final fun filterIsInstance (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataNode;
+	public static final fun get (Lhep/dataforge/data/Data;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/data/DataKt {
+	public static final fun map (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/Data;
+	public static synthetic fun map$default (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/Data;
+	public static final fun reduce (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/DynamicData;
+	public static synthetic fun reduce$default (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/DynamicData;
+}
+
+public abstract interface class hep/dataforge/data/DataNode : hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/data/DataNode$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public abstract fun getItems ()Ljava/util/Map;
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun startAll (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataNode$Companion {
+	public static final field TYPE Ljava/lang/String;
+	public final fun builder (Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataTreeBuilder;
+	public final fun invoke (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataTree;
+}
+
+public final class hep/dataforge/data/DataNode$DefaultImpls {
+	public static fun startAll (Lhep/dataforge/data/DataNode;Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
+	public static fun toMeta (Lhep/dataforge/data/DataNode;)Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataNodeKt {
+	public static final fun asSequence (Lhep/dataforge/data/DataNode;)Lkotlin/sequences/Sequence;
+	public static final fun builder (Lhep/dataforge/data/DataNode;)Lhep/dataforge/data/DataTreeBuilder;
+	public static final fun dataSequence (Lhep/dataforge/data/DataNode;)Lkotlin/sequences/Sequence;
+	public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/Data;)V
+	public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/Data;)V
+	public static final fun filter (Lhep/dataforge/data/DataNode;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/DataNode;
+	public static final fun first (Lhep/dataforge/data/DataNode;)Lhep/dataforge/data/Data;
+	public static final fun get (Lhep/dataforge/data/DataNode;Lhep/dataforge/names/Name;)Lhep/dataforge/data/DataItem;
+	public static final fun get (Lhep/dataforge/data/DataNode;Ljava/lang/String;)Lhep/dataforge/data/DataItem;
+	public static final fun getData (Lhep/dataforge/data/DataItem;)Lhep/dataforge/data/Data;
+	public static final fun getNode (Lhep/dataforge/data/DataItem;)Lhep/dataforge/data/DataNode;
+	public static final fun iterator (Lhep/dataforge/data/DataNode;)Ljava/util/Iterator;
+	public static final fun join (Lhep/dataforge/data/DataNode;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+	public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/DataNode;)V
+	public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/DataNode;)V
+	public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
+	public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
+	public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
+	public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
+	public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+}
+
+public final class hep/dataforge/data/DataTree : hep/dataforge/data/DataNode {
+	public fun getItems ()Ljava/util/Map;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun startAll (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataTreeBuilder {
+	public fun <init> (Lkotlin/reflect/KClass;)V
+	public final fun build ()Lhep/dataforge/data/DataTree;
+	public final fun getType ()Lkotlin/reflect/KClass;
+	public final fun meta (Lhep/dataforge/meta/Meta;)V
+	public final fun meta (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaBuilder;
+	public final fun put (Ljava/lang/String;Lhep/dataforge/data/Data;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/data/DataItem;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/data/DataNode;)V
+	public final fun put (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public final fun set (Lhep/dataforge/names/Name;Lhep/dataforge/data/Data;)V
+	public final fun set (Lhep/dataforge/names/Name;Lhep/dataforge/data/DataItem;)V
+	public final fun set (Lhep/dataforge/names/Name;Lhep/dataforge/data/DataNode;)V
+	public final fun set (Lhep/dataforge/names/Name;Lhep/dataforge/data/DataTreeBuilder;)V
+	public final fun set (Lhep/dataforge/names/NameToken;Lhep/dataforge/data/Data;)V
+	public final fun set (Lhep/dataforge/names/NameToken;Lhep/dataforge/data/DataTreeBuilder;)V
+	public final fun update (Lhep/dataforge/data/DataNode;)V
+}
+
+public final class hep/dataforge/data/Dependencies : kotlin/coroutines/CoroutineContext$Element {
+	public static final field Companion Lhep/dataforge/data/Dependencies$Companion;
+	public fun <init> (Ljava/util/Collection;)V
+	public fun fold (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
+	public fun get (Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
+	public fun getKey ()Lkotlin/coroutines/CoroutineContext$Key;
+	public final fun getValues ()Ljava/util/Collection;
+	public fun minusKey (Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
+	public fun plus (Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
+}
+
+public final class hep/dataforge/data/Dependencies$Companion : kotlin/coroutines/CoroutineContext$Key {
+}
+
+public final class hep/dataforge/data/DynamicData : hep/dataforge/data/DynamicGoal, hep/dataforge/data/Data {
+	public fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
+	public synthetic fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public class hep/dataforge/data/DynamicGoal : hep/dataforge/data/Goal {
+	public fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
+	public synthetic fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun getBlock ()Lkotlin/jvm/functions/Function2;
+	public fun getDependencies ()Ljava/util/Collection;
+	public final fun getResult ()Lkotlinx/coroutines/Deferred;
+	public fun reset ()V
+	public fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
+}
+
+public final class hep/dataforge/data/FragmentRule {
+	public field result Lkotlin/jvm/functions/Function2;
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaBuilder;)V
+	public final fun getMeta ()Lhep/dataforge/meta/MetaBuilder;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getResult ()Lkotlin/jvm/functions/Function2;
+	public final fun result (Lkotlin/jvm/functions/Function2;)V
+	public final fun setMeta (Lhep/dataforge/meta/MetaBuilder;)V
+	public final fun setResult (Lkotlin/jvm/functions/Function2;)V
+}
+
+public abstract interface class hep/dataforge/data/Goal {
+	public static final field Companion Lhep/dataforge/data/Goal$Companion;
+	public abstract fun getDependencies ()Ljava/util/Collection;
+	public abstract fun getResult ()Lkotlinx/coroutines/Deferred;
+	public abstract fun reset ()V
+	public abstract fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
+}
+
+public final class hep/dataforge/data/Goal$Companion {
+}
+
+public final class hep/dataforge/data/GoalKt {
+	public static final fun await (Lhep/dataforge/data/Goal;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+	public static final fun isComplete (Lhep/dataforge/data/Goal;)Z
+	public static final fun map (Lhep/dataforge/data/Goal;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/Goal;
+	public static synthetic fun map$default (Lhep/dataforge/data/Goal;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/Goal;
+	public static final fun reduce (Ljava/util/Collection;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/Goal;
+	public static final fun reduce (Ljava/util/Map;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/Goal;
+	public static synthetic fun reduce$default (Ljava/util/Collection;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/Goal;
+	public static synthetic fun reduce$default (Ljava/util/Map;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/Goal;
+}
+
+public abstract interface class hep/dataforge/data/GroupRule {
+	public static final field Companion Lhep/dataforge/data/GroupRule$Companion;
+	public abstract fun invoke (Lhep/dataforge/data/DataNode;)Ljava/util/Map;
+}
+
+public final class hep/dataforge/data/GroupRule$Companion {
+	public final fun byMeta (Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/GroupRule;
+	public final fun byValue (Ljava/lang/String;Ljava/lang/String;)Lhep/dataforge/data/GroupRule;
+}
+
+public final class hep/dataforge/data/JoinGroup {
+	public field result Lkotlin/jvm/functions/Function3;
+	public fun <init> (Ljava/lang/String;Lhep/dataforge/data/DataNode;)V
+	public final fun getMeta ()Lhep/dataforge/meta/MetaBuilder;
+	public final fun getName ()Ljava/lang/String;
+	public final fun getResult ()Lkotlin/jvm/functions/Function3;
+	public final fun result (Lkotlin/jvm/functions/Function3;)V
+	public final fun setMeta (Lhep/dataforge/meta/MetaBuilder;)V
+	public final fun setName (Ljava/lang/String;)V
+	public final fun setResult (Lkotlin/jvm/functions/Function3;)V
+}
+
+public final class hep/dataforge/data/MapAction : hep/dataforge/data/Action {
+	public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
+	public final fun getInputType ()Lkotlin/reflect/KClass;
+	public final fun getOutputType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public fun isTerminal ()Z
+}
+
+public final class hep/dataforge/data/MapActionBuilder {
+	public field result Lkotlin/jvm/functions/Function3;
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaBuilder;Lhep/dataforge/meta/Meta;)V
+	public final fun getActionMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getMeta ()Lhep/dataforge/meta/MetaBuilder;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getResult ()Lkotlin/jvm/functions/Function3;
+	public final fun result (Lkotlin/jvm/functions/Function3;)V
+	public final fun setMeta (Lhep/dataforge/meta/MetaBuilder;)V
+	public final fun setName (Lhep/dataforge/names/Name;)V
+	public final fun setResult (Lkotlin/jvm/functions/Function3;)V
+}
+
+public final class hep/dataforge/data/NamedData : hep/dataforge/data/Data {
+	public fun <init> (Ljava/lang/String;Lhep/dataforge/data/Data;)V
+	public fun getDependencies ()Ljava/util/Collection;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Ljava/lang/String;
+	public fun getResult ()Lkotlinx/coroutines/Deferred;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun reset ()V
+	public fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/ReduceAction : hep/dataforge/data/Action {
+	public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
+	public final fun getInputType ()Lkotlin/reflect/KClass;
+	public final fun getOutputType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public fun isTerminal ()Z
+}
+
+public final class hep/dataforge/data/ReduceActionKt {
+	public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/data/ReduceGroupBuilder {
+	public fun <init> (Lhep/dataforge/meta/Meta;)V
+	public final fun byValue (Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public static synthetic fun byValue$default (Lhep/dataforge/data/ReduceGroupBuilder;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public final fun getActionMeta ()Lhep/dataforge/meta/Meta;
+	public final fun group (Ljava/lang/String;Lhep/dataforge/data/DataFilter;Lkotlin/jvm/functions/Function1;)V
+	public final fun group (Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)V
+	public final fun result (Ljava/lang/String;Lkotlin/jvm/functions/Function3;)V
+}
+
+public final class hep/dataforge/data/SplitAction : hep/dataforge/data/Action {
+	public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
+	public final fun getInputType ()Lkotlin/reflect/KClass;
+	public final fun getOutputType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public fun isTerminal ()Z
+}
+
+public final class hep/dataforge/data/SplitBuilder {
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public final fun fragment (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/data/StaticData : hep/dataforge/data/StaticGoal, hep/dataforge/data/Data {
+	public fun <init> (Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public class hep/dataforge/data/StaticGoal : hep/dataforge/data/Goal {
+	public fun <init> (Ljava/lang/Object;)V
+	public fun getDependencies ()Ljava/util/Collection;
+	public fun getResult ()Lkotlinx/coroutines/Deferred;
+	public final fun getValue ()Ljava/lang/Object;
+	public fun reset ()V
+	public fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
+}
+
+public final class hep/dataforge/data/TypeFilteredDataNode : hep/dataforge/data/DataNode {
+	public fun <init> (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)V
+	public fun getItems ()Ljava/util/Map;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getOrigin ()Lhep/dataforge/data/DataNode;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun startAll (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
diff --git a/dataforge-io/api/dataforge-io.api b/dataforge-io/api/dataforge-io.api
new file mode 100644
index 00000000..1b8f876b
--- /dev/null
+++ b/dataforge-io/api/dataforge-io.api
@@ -0,0 +1,469 @@
+public final class hep/dataforge/io/BinaryMetaFormat : hep/dataforge/io/MetaFormat, hep/dataforge/io/MetaFormatFactory {
+	public static final field INSTANCE Lhep/dataforge/io/BinaryMetaFormat;
+	public fun getKey ()S
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getShortName ()Ljava/lang/String;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/MetaFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public final fun readMetaItem (Lkotlinx/io/Input;)Lhep/dataforge/meta/MetaItem;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+	public final fun writeValue (Lkotlinx/io/Output;Lhep/dataforge/values/Value;)V
+}
+
+public final class hep/dataforge/io/BinaryView : kotlinx/io/Binary {
+	public fun <init> (Lkotlinx/io/Binary;II)V
+	public fun getSize ()I
+	public fun read (IILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+}
+
+public abstract interface class hep/dataforge/io/Consumer {
+	public abstract fun consume (Lhep/dataforge/io/Envelope;)V
+}
+
+public final class hep/dataforge/io/DoubleIOFormat : hep/dataforge/io/IOFormat, hep/dataforge/io/IOFormatFactory {
+	public static final field INSTANCE Lhep/dataforge/io/DoubleIOFormat;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/IOFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun readObject (Lkotlinx/io/Input;)Ljava/lang/Double;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeObject (Lkotlinx/io/Output;D)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public abstract interface class hep/dataforge/io/Envelope {
+	public static final field Companion Lhep/dataforge/io/Envelope$Companion;
+	public abstract fun getData ()Lkotlinx/io/Binary;
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/io/Envelope$Companion {
+	public final fun getENVELOPE_DATA_ID_KEY ()Lhep/dataforge/names/Name;
+	public final fun getENVELOPE_DATA_TYPE_KEY ()Lhep/dataforge/names/Name;
+	public final fun getENVELOPE_DESCRIPTION_KEY ()Lhep/dataforge/names/Name;
+	public final fun getENVELOPE_NAME_KEY ()Lhep/dataforge/names/Name;
+	public final fun getENVELOPE_NODE_KEY ()Lhep/dataforge/names/Name;
+	public final fun getENVELOPE_TYPE_KEY ()Lhep/dataforge/names/Name;
+	public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/io/Envelope;
+}
+
+public final class hep/dataforge/io/EnvelopeBuilder : hep/dataforge/io/Envelope {
+	public fun <init> ()V
+	public final fun data (Lkotlin/jvm/functions/Function1;)V
+	public fun getData ()Lkotlinx/io/Binary;
+	public final fun getDataID ()Ljava/lang/String;
+	public final fun getDataType ()Ljava/lang/String;
+	public final fun getDescription ()Ljava/lang/String;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Ljava/lang/String;
+	public final fun getType ()Ljava/lang/String;
+	public final fun meta (Lkotlin/jvm/functions/Function1;)V
+	public final fun seal ()Lhep/dataforge/io/Envelope;
+	public fun setData (Lkotlinx/io/Binary;)V
+	public final fun setDataID (Ljava/lang/String;)V
+	public final fun setDataType (Ljava/lang/String;)V
+	public final fun setDescription (Ljava/lang/String;)V
+	public fun setMeta (Lhep/dataforge/meta/Meta;)V
+	public final fun setName (Ljava/lang/String;)V
+	public final fun setType (Ljava/lang/String;)V
+}
+
+public abstract interface class hep/dataforge/io/EnvelopeFormat : hep/dataforge/io/IOFormat {
+	public abstract fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public abstract fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public abstract fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public abstract fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public abstract fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+}
+
+public final class hep/dataforge/io/EnvelopeFormat$DefaultImpls {
+	public static fun getDefaultMetaFormat (Lhep/dataforge/io/EnvelopeFormat;)Lhep/dataforge/io/MetaFormatFactory;
+	public static synthetic fun writeEnvelope$default (Lhep/dataforge/io/EnvelopeFormat;Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
+	public static fun writeObject (Lhep/dataforge/io/EnvelopeFormat;Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+}
+
+public abstract interface class hep/dataforge/io/EnvelopeFormatFactory : hep/dataforge/io/EnvelopeFormat, hep/dataforge/io/IOFormatFactory {
+	public static final field Companion Lhep/dataforge/io/EnvelopeFormatFactory$Companion;
+	public static final field ENVELOPE_FORMAT_TYPE Ljava/lang/String;
+	public abstract fun getName ()Lhep/dataforge/names/Name;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/EnvelopeFormat;
+	public abstract fun peekFormat (Lhep/dataforge/io/IOPlugin;Lkotlinx/io/Input;)Lhep/dataforge/io/EnvelopeFormat;
+}
+
+public final class hep/dataforge/io/EnvelopeFormatFactory$Companion {
+	public static final field ENVELOPE_FORMAT_TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/EnvelopeFormatFactory$DefaultImpls {
+	public static fun getDefaultMetaFormat (Lhep/dataforge/io/EnvelopeFormatFactory;)Lhep/dataforge/io/MetaFormatFactory;
+	public static fun getName (Lhep/dataforge/io/EnvelopeFormatFactory;)Lhep/dataforge/names/Name;
+	public static fun getType (Lhep/dataforge/io/EnvelopeFormatFactory;)Lkotlin/reflect/KClass;
+	public static fun toMeta (Lhep/dataforge/io/EnvelopeFormatFactory;)Lhep/dataforge/meta/Meta;
+	public static fun writeObject (Lhep/dataforge/io/EnvelopeFormatFactory;Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+}
+
+public final class hep/dataforge/io/EnvelopeFormatKt {
+	public static final fun read (Lhep/dataforge/io/EnvelopeFormat;Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+}
+
+public final class hep/dataforge/io/EnvelopeKt {
+	public static final fun contentEquals (Lhep/dataforge/io/Envelope;Lhep/dataforge/io/Envelope;)Z
+	public static final fun dataEquals (Lhep/dataforge/io/Envelope;Lhep/dataforge/io/Envelope;)Z
+	public static final fun getDataID (Lhep/dataforge/io/Envelope;)Ljava/lang/String;
+	public static final fun getDataType (Lhep/dataforge/io/Envelope;)Ljava/lang/String;
+	public static final fun getDescription (Lhep/dataforge/io/Envelope;)Ljava/lang/String;
+	public static final fun getType (Lhep/dataforge/io/Envelope;)Ljava/lang/String;
+	public static final fun metaEquals (Lhep/dataforge/io/Envelope;Lhep/dataforge/io/Envelope;)Z
+	public static final fun withMetaLayers (Lhep/dataforge/io/Envelope;[Lhep/dataforge/meta/Meta;)Lhep/dataforge/io/Envelope;
+}
+
+public final class hep/dataforge/io/EnvelopePart {
+	public fun <init> (Lkotlinx/io/Binary;Lhep/dataforge/meta/Meta;)V
+	public final fun component1 ()Lkotlinx/io/Binary;
+	public final fun component2 ()Lhep/dataforge/meta/Meta;
+	public final fun copy (Lkotlinx/io/Binary;Lhep/dataforge/meta/Meta;)Lhep/dataforge/io/EnvelopePart;
+	public static synthetic fun copy$default (Lhep/dataforge/io/EnvelopePart;Lkotlinx/io/Binary;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/io/EnvelopePart;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getBinary ()Lkotlinx/io/Binary;
+	public final fun getDescription ()Lhep/dataforge/meta/Meta;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/EnvelopePartsKt {
+	public static final fun envelope (Lhep/dataforge/io/EnvelopePart;Lhep/dataforge/io/EnvelopeFormat;)Lhep/dataforge/io/Envelope;
+	public static final fun envelope (Lhep/dataforge/io/EnvelopePart;Lhep/dataforge/io/IOPlugin;)Lhep/dataforge/io/Envelope;
+	public static final fun envelopes (Lhep/dataforge/io/EnvelopeBuilder;Ljava/util/List;Lhep/dataforge/io/EnvelopeFormat;Ljava/lang/String;)V
+	public static synthetic fun envelopes$default (Lhep/dataforge/io/EnvelopeBuilder;Ljava/util/List;Lhep/dataforge/io/EnvelopeFormat;Ljava/lang/String;ILjava/lang/Object;)V
+	public static final fun getName (Lhep/dataforge/io/EnvelopePart;)Ljava/lang/String;
+	public static final fun multipart (Lhep/dataforge/io/EnvelopeBuilder;Ljava/util/List;Ljava/lang/String;)V
+	public static synthetic fun multipart$default (Lhep/dataforge/io/EnvelopeBuilder;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)V
+	public static final fun parts (Lhep/dataforge/io/Envelope;)Ljava/util/List;
+}
+
+public final class hep/dataforge/io/FileIOKt {
+	public static final fun append (Ljava/nio/file/Path;Lkotlin/jvm/functions/Function1;)V
+	public static final fun getDATA_FILE_NAME (Lhep/dataforge/io/IOPlugin$Companion;)Ljava/lang/String;
+	public static final fun getMETA_FILE_NAME (Lhep/dataforge/io/IOPlugin$Companion;)Ljava/lang/String;
+	public static final fun peekBinaryFormat (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;)Lhep/dataforge/io/EnvelopeFormat;
+	public static final fun read (Ljava/nio/file/Path;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun readEnvelope (Ljava/nio/file/Path;Lhep/dataforge/io/EnvelopeFormat;)Lhep/dataforge/io/Envelope;
+	public static final fun readEnvelopeFile (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;ZLkotlin/jvm/functions/Function2;)Lhep/dataforge/io/Envelope;
+	public static synthetic fun readEnvelopeFile$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lhep/dataforge/io/Envelope;
+	public static final fun readMetaFile (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/MetaFormat;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public static synthetic fun readMetaFile$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/MetaFormat;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/Meta;
+	public static final fun rewrite (Ljava/nio/file/Path;Lkotlin/jvm/functions/Function1;)V
+	public static final fun write (Ljava/nio/file/Path;Lkotlin/jvm/functions/Function1;)V
+	public static final fun writeEnvelopeDirectory (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;)V
+	public static synthetic fun writeEnvelopeDirectory$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;ILjava/lang/Object;)V
+	public static final fun writeEnvelopeFile (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/EnvelopeFormat;Lhep/dataforge/io/MetaFormatFactory;)V
+	public static synthetic fun writeEnvelopeFile$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/EnvelopeFormat;Lhep/dataforge/io/MetaFormatFactory;ILjava/lang/Object;)V
+	public static final fun writeMetaFile (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/meta/Meta;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public static synthetic fun writeMetaFile$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/meta/Meta;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)V
+	public static final fun writeToFile (Lhep/dataforge/io/IOFormat;Ljava/nio/file/Path;Ljava/lang/Object;)V
+}
+
+public abstract interface class hep/dataforge/io/IOFormat : hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/io/IOFormat$Companion;
+	public abstract fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public abstract fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/IOFormat$Companion {
+	public final fun getMETA_KEY ()Lhep/dataforge/names/Name;
+	public final fun getNAME_KEY ()Lhep/dataforge/names/Name;
+}
+
+public abstract interface class hep/dataforge/io/IOFormatFactory : hep/dataforge/context/Factory, hep/dataforge/context/Named, hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/io/IOFormatFactory$Companion;
+	public static final field IO_FORMAT_TYPE Ljava/lang/String;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/io/IOFormatFactory$Companion {
+	public static final field IO_FORMAT_TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/IOFormatFactory$DefaultImpls {
+	public static fun toMeta (Lhep/dataforge/io/IOFormatFactory;)Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/io/IOFormatKt {
+	public static final fun fill (Lkotlinx/io/pool/ObjectPool;Lkotlin/jvm/functions/Function1;)Ljava/nio/ByteBuffer;
+	public static final fun readWith (Lkotlinx/io/Binary;Lhep/dataforge/io/IOFormat;)Ljava/lang/Object;
+	public static final fun readWith (Lkotlinx/io/Input;Lhep/dataforge/io/IOFormat;)Ljava/lang/Object;
+	public static final fun toBinary (Lhep/dataforge/io/IOFormat;Ljava/lang/Object;)Lkotlinx/io/Binary;
+	public static final fun writeWith (Lkotlinx/io/Output;Lhep/dataforge/io/IOFormat;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/IOPlugin : hep/dataforge/context/AbstractPlugin {
+	public static final field Companion Lhep/dataforge/io/IOPlugin$Companion;
+	public fun <init> (Lhep/dataforge/meta/Meta;)V
+	public fun content (Ljava/lang/String;)Ljava/util/Map;
+	public final fun getEnvelopeFormatFactories ()Ljava/util/Collection;
+	public final fun getIoFormatFactories ()Ljava/util/Collection;
+	public final fun getMetaFormatFactories ()Ljava/util/Collection;
+	public fun getTag ()Lhep/dataforge/context/PluginTag;
+	public final fun resolveEnvelopeFormat (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/io/EnvelopeFormat;
+	public final fun resolveIOFormat (Lhep/dataforge/meta/MetaItem;Lkotlin/reflect/KClass;)Lhep/dataforge/io/IOFormat;
+	public final fun resolveMetaFormat (Ljava/lang/String;Lhep/dataforge/meta/Meta;)Lhep/dataforge/io/MetaFormat;
+	public final fun resolveMetaFormat (SLhep/dataforge/meta/Meta;)Lhep/dataforge/io/MetaFormat;
+	public static synthetic fun resolveMetaFormat$default (Lhep/dataforge/io/IOPlugin;Ljava/lang/String;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/io/MetaFormat;
+	public static synthetic fun resolveMetaFormat$default (Lhep/dataforge/io/IOPlugin;SLhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/io/MetaFormat;
+}
+
+public final class hep/dataforge/io/IOPlugin$Companion : hep/dataforge/context/PluginFactory {
+	public final fun getDefaultEnvelopeFormats ()Ljava/util/List;
+	public final fun getDefaultMetaFormats ()Ljava/util/List;
+	public fun getTag ()Lhep/dataforge/context/PluginTag;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/IOPlugin;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/io/IOPluginKt {
+	public static final fun getIo (Lhep/dataforge/context/Context;)Lhep/dataforge/io/IOPlugin;
+}
+
+public final class hep/dataforge/io/IoMiscKt {
+	public static final fun Binary (ILkotlin/jvm/functions/Function1;)Lkotlinx/io/Binary;
+	public static synthetic fun Binary$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/io/Binary;
+	public static final fun buildByteArray (ILkotlin/jvm/functions/Function1;)[B
+	public static synthetic fun buildByteArray$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)[B
+	public static final fun get (Lkotlinx/io/Binary;Lkotlin/ranges/IntRange;)Lhep/dataforge/io/BinaryView;
+	public static final fun readRawString (Lkotlinx/io/Input;I)Ljava/lang/String;
+	public static final fun view (Lkotlinx/io/Binary;II)Lhep/dataforge/io/BinaryView;
+	public static final fun writeRawString (Lkotlinx/io/Output;Ljava/lang/String;)V
+}
+
+public final class hep/dataforge/io/JsonMetaFormat : hep/dataforge/io/MetaFormat {
+	public static final field Companion Lhep/dataforge/io/JsonMetaFormat$Companion;
+	public fun <init> ()V
+	public fun <init> (Lkotlinx/serialization/json/Json;)V
+	public synthetic fun <init> (Lkotlinx/serialization/json/Json;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/JsonMetaFormat$Companion : hep/dataforge/io/MetaFormatFactory {
+	public final fun getDEFAULT_JSON ()Lkotlinx/serialization/json/Json;
+	public fun getKey ()S
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getShortName ()Ljava/lang/String;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/MetaFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/ListIOFormat : hep/dataforge/io/IOFormat {
+	public fun <init> (Lhep/dataforge/io/IOFormat;)V
+	public final fun getFormat ()Lhep/dataforge/io/IOFormat;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readObject (Lkotlinx/io/Input;)Ljava/util/List;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+	public fun writeObject (Lkotlinx/io/Output;Ljava/util/List;)V
+}
+
+public abstract interface class hep/dataforge/io/MetaFormat : hep/dataforge/io/IOFormat {
+	public abstract fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public abstract fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public abstract fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public abstract fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+}
+
+public final class hep/dataforge/io/MetaFormat$DefaultImpls {
+	public static synthetic fun readMeta$default (Lhep/dataforge/io/MetaFormat;Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/Meta;
+	public static fun readObject (Lhep/dataforge/io/MetaFormat;Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public static synthetic fun writeMeta$default (Lhep/dataforge/io/MetaFormat;Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)V
+	public static fun writeObject (Lhep/dataforge/io/MetaFormat;Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+}
+
+public abstract interface class hep/dataforge/io/MetaFormatFactory : hep/dataforge/io/IOFormatFactory, hep/dataforge/io/MetaFormat {
+	public static final field Companion Lhep/dataforge/io/MetaFormatFactory$Companion;
+	public static final field META_FORMAT_TYPE Ljava/lang/String;
+	public abstract fun getKey ()S
+	public abstract fun getName ()Lhep/dataforge/names/Name;
+	public abstract fun getShortName ()Ljava/lang/String;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/MetaFormat;
+}
+
+public final class hep/dataforge/io/MetaFormatFactory$Companion {
+	public static final field META_FORMAT_TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/MetaFormatFactory$DefaultImpls {
+	public static fun getKey (Lhep/dataforge/io/MetaFormatFactory;)S
+	public static fun getName (Lhep/dataforge/io/MetaFormatFactory;)Lhep/dataforge/names/Name;
+	public static fun getType (Lhep/dataforge/io/MetaFormatFactory;)Lkotlin/reflect/KClass;
+	public static fun readObject (Lhep/dataforge/io/MetaFormatFactory;Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public static fun toMeta (Lhep/dataforge/io/MetaFormatFactory;)Lhep/dataforge/meta/Meta;
+	public static fun writeObject (Lhep/dataforge/io/MetaFormatFactory;Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+}
+
+public final class hep/dataforge/io/MetaFormatKt {
+	public static final fun parse (Lhep/dataforge/io/MetaFormat;Ljava/lang/String;)Lhep/dataforge/meta/Meta;
+	public static final fun parse (Lhep/dataforge/io/MetaFormatFactory;Ljava/lang/String;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Meta;
+	public static final fun toString (Lhep/dataforge/meta/Meta;Lhep/dataforge/io/MetaFormat;)Ljava/lang/String;
+	public static final fun toString (Lhep/dataforge/meta/Meta;Lhep/dataforge/io/MetaFormatFactory;)Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/PartialEnvelope {
+	public synthetic fun <init> (Lhep/dataforge/meta/Meta;ILkotlin/ULong;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Lhep/dataforge/meta/Meta;
+	public final fun component2-pVg5ArA ()I
+	public final fun component3-6VbMDqA ()Lkotlin/ULong;
+	public final fun copy-BMK4sig (Lhep/dataforge/meta/Meta;ILkotlin/ULong;)Lhep/dataforge/io/PartialEnvelope;
+	public static synthetic fun copy-BMK4sig$default (Lhep/dataforge/io/PartialEnvelope;Lhep/dataforge/meta/Meta;ILkotlin/ULong;ILjava/lang/Object;)Lhep/dataforge/io/PartialEnvelope;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getDataOffset-pVg5ArA ()I
+	public final fun getDataSize-6VbMDqA ()Lkotlin/ULong;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/ProxyEnvelope : hep/dataforge/io/Envelope {
+	public fun <init> (Lhep/dataforge/io/Envelope;[Lhep/dataforge/meta/Meta;)V
+	public fun getData ()Lkotlinx/io/Binary;
+	public fun getMeta ()Lhep/dataforge/meta/Laminate;
+	public synthetic fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getSource ()Lhep/dataforge/io/Envelope;
+}
+
+public abstract interface class hep/dataforge/io/Responder {
+	public abstract fun respond (Lhep/dataforge/io/Envelope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/io/SimpleEnvelope : hep/dataforge/io/Envelope {
+	public fun <init> (Lhep/dataforge/meta/Meta;Lkotlinx/io/Binary;)V
+	public fun getData ()Lkotlinx/io/Binary;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/io/StreamsIOKt {
+	public static final fun read (Ljava/io/InputStream;ILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun read (Ljava/io/InputStream;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun readBlocking (Ljava/io/InputStream;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun write (Ljava/io/OutputStream;Lkotlin/jvm/functions/Function1;)V
+}
+
+public final class hep/dataforge/io/TaggedEnvelopeFormat : hep/dataforge/io/EnvelopeFormat {
+	public static final field Companion Lhep/dataforge/io/TaggedEnvelopeFormat$Companion;
+	public fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;)V
+	public synthetic fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public final fun getIo ()Lhep/dataforge/io/IOPlugin;
+	public final fun getVersion ()Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/TaggedEnvelopeFormat$Companion : hep/dataforge/io/EnvelopeFormatFactory {
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/EnvelopeFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun peekFormat (Lhep/dataforge/io/IOPlugin;Lkotlinx/io/Input;)Lhep/dataforge/io/EnvelopeFormat;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/TaggedEnvelopeFormat$VERSION : java/lang/Enum {
+	public static final field DF02 Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;
+	public static final field DF03 Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;
+	public final fun getTagSize-pVg5ArA ()I
+	public static fun valueOf (Ljava/lang/String;)Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;
+	public static fun values ()[Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;
+}
+
+public final class hep/dataforge/io/TaglessEnvelopeFormat : hep/dataforge/io/EnvelopeFormat {
+	public static final field Companion Lhep/dataforge/io/TaglessEnvelopeFormat$Companion;
+	public static final field DATA_LENGTH_PROPERTY Ljava/lang/String;
+	public static final field DATA_START_PROPERTY Ljava/lang/String;
+	public static final field DEFAULT_DATA_START Ljava/lang/String;
+	public static final field DEFAULT_META_START Ljava/lang/String;
+	public static final field META_LENGTH_PROPERTY Ljava/lang/String;
+	public static final field META_START_PROPERTY Ljava/lang/String;
+	public static final field META_TYPE_PROPERTY Ljava/lang/String;
+	public static final field TAGLESS_ENVELOPE_HEADER Ljava/lang/String;
+	public static final field TAGLESS_ENVELOPE_TYPE Ljava/lang/String;
+	public static final field code I
+	public fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public final fun getIo ()Lhep/dataforge/io/IOPlugin;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/TaglessEnvelopeFormat$Companion : hep/dataforge/io/EnvelopeFormatFactory {
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/EnvelopeFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun peekFormat (Lhep/dataforge/io/IOPlugin;Lkotlinx/io/Input;)Lhep/dataforge/io/EnvelopeFormat;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/ValueIOFormat : hep/dataforge/io/IOFormat, hep/dataforge/io/IOFormatFactory {
+	public static final field INSTANCE Lhep/dataforge/io/ValueIOFormat;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/IOFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/values/Value;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/values/Value;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
diff --git a/dataforge-io/dataforge-io-yaml/api/dataforge-io-yaml.api b/dataforge-io/dataforge-io-yaml/api/dataforge-io-yaml.api
new file mode 100644
index 00000000..de7b3ab2
--- /dev/null
+++ b/dataforge-io/dataforge-io-yaml/api/dataforge-io-yaml.api
@@ -0,0 +1,59 @@
+public final class hep/dataforge/io/yaml/FrontMatterEnvelopeFormat : hep/dataforge/io/EnvelopeFormat {
+	public static final field Companion Lhep/dataforge/io/yaml/FrontMatterEnvelopeFormat$Companion;
+	public static final field SEPARATOR Ljava/lang/String;
+	public fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/yaml/FrontMatterEnvelopeFormat$Companion : hep/dataforge/io/EnvelopeFormatFactory {
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/EnvelopeFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun peekFormat (Lhep/dataforge/io/IOPlugin;Lkotlinx/io/Input;)Lhep/dataforge/io/EnvelopeFormat;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/yaml/YamlMetaFormat : hep/dataforge/io/MetaFormat {
+	public static final field Companion Lhep/dataforge/io/yaml/YamlMetaFormat$Companion;
+	public fun <init> (Lhep/dataforge/meta/Meta;)V
+	public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/yaml/YamlMetaFormat$Companion : hep/dataforge/io/MetaFormatFactory {
+	public fun getKey ()S
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getShortName ()Ljava/lang/String;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/MetaFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api
new file mode 100644
index 00000000..5fed772c
--- /dev/null
+++ b/dataforge-meta/api/dataforge-meta.api
@@ -0,0 +1,1016 @@
+public abstract class hep/dataforge/meta/AbstractMetaNode : hep/dataforge/meta/MetaBase, hep/dataforge/meta/MetaNode {
+	public fun <init> ()V
+	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public abstract class hep/dataforge/meta/AbstractMutableMeta : hep/dataforge/meta/AbstractMetaNode, hep/dataforge/meta/MutableMeta {
+	public fun <init> ()V
+	public fun getItems ()Ljava/util/Map;
+	protected final fun get_items ()Ljava/util/Map;
+	protected fun replaceItem (Lhep/dataforge/names/NameToken;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MetaItem;)V
+	public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
+	protected final fun wrapItem (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/meta/MetaItem;
+	protected abstract fun wrapNode (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MutableMeta;
+}
+
+public final class hep/dataforge/meta/Config : hep/dataforge/meta/AbstractMutableMeta, hep/dataforge/meta/ObservableMeta {
+	public static final field ConfigSerializer Lhep/dataforge/meta/Config$ConfigSerializer;
+	public fun <init> ()V
+	public synthetic fun empty$dataforge_meta ()Lhep/dataforge/meta/MutableMeta;
+	public fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V
+	public fun removeListener (Ljava/lang/Object;)V
+	public synthetic fun wrapNode (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MutableMeta;
+}
+
+public final class hep/dataforge/meta/Config$ConfigSerializer : kotlinx/serialization/KSerializer {
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/Config;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public final fun empty ()Lhep/dataforge/meta/Config;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/meta/Config;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/meta/ConfigKt {
+	public static final fun asConfig (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Config;
+	public static final fun get (Lhep/dataforge/meta/Config;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
+}
+
+public abstract interface class hep/dataforge/meta/Configurable : hep/dataforge/meta/MutableItemProvider, hep/dataforge/meta/descriptors/Described {
+	public abstract fun getConfig ()Lhep/dataforge/meta/Config;
+	public abstract fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public abstract fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public abstract fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
+	public abstract fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+}
+
+public final class hep/dataforge/meta/Configurable$DefaultImpls {
+	public static fun getDefaultItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static fun getDescriptor (Lhep/dataforge/meta/Configurable;)Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public static fun getItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static fun setItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
+	public static fun validateItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+}
+
+public final class hep/dataforge/meta/ConfigurableKt {
+	public static final fun config (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun config$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun configure (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Configurable;
+	public static final fun configure (Lhep/dataforge/meta/Configurable;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+	public static final fun getItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
+	public static final fun node (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun node$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun setItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public static final fun setItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
+	public static final fun setItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
+	public static final fun setItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
+	public static final fun setItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;Lhep/dataforge/values/Value;)V
+	public static final fun spec (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun spec (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun spec$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun spec$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+}
+
+public abstract interface annotation class hep/dataforge/meta/DFBuilder : java/lang/annotation/Annotation {
+}
+
+public abstract interface annotation class hep/dataforge/meta/DFExperimental : java/lang/annotation/Annotation {
+}
+
+public final class hep/dataforge/meta/GetIndexedKt {
+	public static final fun getIndexed (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Ljava/util/Map;
+	public static final fun getIndexed (Lhep/dataforge/meta/Meta;Ljava/lang/String;)Ljava/util/Map;
+	public static final fun getIndexed (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/Name;)Ljava/util/Map;
+	public static final fun getIndexed (Lhep/dataforge/meta/MetaNode;Ljava/lang/String;)Ljava/util/Map;
+}
+
+public final class hep/dataforge/meta/ItemDelegateKt {
+	public static final fun boolean (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun boolean (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun boolean (Lhep/dataforge/meta/ItemProvider;ZLhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/ItemProvider;ZLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun convert (Lkotlin/properties/ReadOnlyProperty;Lhep/dataforge/meta/transformations/MetaConverter;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun convert (Lkotlin/properties/ReadOnlyProperty;Lhep/dataforge/meta/transformations/MetaConverter;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun convert (Lkotlin/properties/ReadOnlyProperty;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun double (Lhep/dataforge/meta/ItemProvider;DLhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun double (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun double$default (Lhep/dataforge/meta/ItemProvider;DLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun double$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun float (Lhep/dataforge/meta/ItemProvider;FLhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun float (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun float$default (Lhep/dataforge/meta/ItemProvider;FLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun float$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun int (Lhep/dataforge/meta/ItemProvider;ILhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun int (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun int$default (Lhep/dataforge/meta/ItemProvider;ILhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun int$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun item (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun item$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun long (Lhep/dataforge/meta/ItemProvider;JLhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun long (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun long$default (Lhep/dataforge/meta/ItemProvider;JLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun long$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun node (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun node$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun number (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun number (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun number (Lhep/dataforge/meta/ItemProvider;Ljava/lang/Number;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/ItemProvider;Ljava/lang/Number;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun string (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun string (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun string (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun value (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun value$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+}
+
+public abstract interface class hep/dataforge/meta/ItemProvider {
+	public static final field Companion Lhep/dataforge/meta/ItemProvider$Companion;
+	public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+}
+
+public final class hep/dataforge/meta/ItemProvider$Companion {
+	public final fun getEMPTY ()Lhep/dataforge/meta/ItemProvider;
+}
+
+public final class hep/dataforge/meta/JsonMeta : hep/dataforge/meta/MetaBase {
+	public static final field Companion Lhep/dataforge/meta/JsonMeta$Companion;
+	public static final field JSON_ARRAY_KEY Ljava/lang/String;
+	public fun <init> (Lkotlinx/serialization/json/JsonObject;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public synthetic fun <init> (Lkotlinx/serialization/json/JsonObject;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getItems ()Ljava/util/Map;
+}
+
+public final class hep/dataforge/meta/JsonMeta$Companion {
+}
+
+public final class hep/dataforge/meta/JsonMetaKt {
+	public static final fun toJson (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lkotlinx/serialization/json/JsonObject;
+	public static final fun toJson (Lhep/dataforge/values/Value;Lhep/dataforge/meta/descriptors/ValueDescriptor;)Lkotlinx/serialization/json/JsonElement;
+	public static synthetic fun toJson$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonObject;
+	public static synthetic fun toJson$default (Lhep/dataforge/values/Value;Lhep/dataforge/meta/descriptors/ValueDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonElement;
+	public static final fun toMeta (Lkotlinx/serialization/json/JsonObject;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/JsonMeta;
+	public static synthetic fun toMeta$default (Lkotlinx/serialization/json/JsonObject;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/JsonMeta;
+	public static final fun toMetaItem (Lkotlinx/serialization/json/JsonElement;Lhep/dataforge/meta/descriptors/ItemDescriptor;)Lhep/dataforge/meta/MetaItem;
+	public static synthetic fun toMetaItem$default (Lkotlinx/serialization/json/JsonElement;Lhep/dataforge/meta/descriptors/ItemDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/MetaItem;
+	public static final fun toValue (Lkotlinx/serialization/json/JsonPrimitive;Lhep/dataforge/meta/descriptors/ValueDescriptor;)Lhep/dataforge/values/Value;
+}
+
+public final class hep/dataforge/meta/Laminate : hep/dataforge/meta/MetaBase {
+	public static final field Companion Lhep/dataforge/meta/Laminate$Companion;
+	public fun <init> (Ljava/util/List;)V
+	public fun getItems ()Ljava/util/Map;
+	public final fun getLayers ()Ljava/util/List;
+	public final fun merge ()Lhep/dataforge/meta/SealedMeta;
+}
+
+public final class hep/dataforge/meta/Laminate$Companion {
+	public final fun getMergeRule ()Lkotlin/jvm/functions/Function1;
+	public final fun getReplaceRule ()Lkotlin/jvm/functions/Function1;
+}
+
+public final class hep/dataforge/meta/LaminateKt {
+	public static final fun Laminate ([Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Laminate;
+	public static final fun getFirst (Lhep/dataforge/meta/Laminate;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static final fun withBottom (Lhep/dataforge/meta/Laminate;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Laminate;
+	public static final fun withTop (Lhep/dataforge/meta/Laminate;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Laminate;
+}
+
+public final class hep/dataforge/meta/MapMetaKt {
+	public static final fun toMap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Ljava/util/Map;
+	public static synthetic fun toMap$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Ljava/util/Map;
+	public static final fun toMeta (Ljava/util/Map;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public static synthetic fun toMeta$default (Ljava/util/Map;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/Meta;
+}
+
+public abstract interface class hep/dataforge/meta/Meta : hep/dataforge/meta/ItemProvider, hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/meta/Meta$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public static final field VALUE_KEY Ljava/lang/String;
+	public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public abstract fun getItems ()Ljava/util/Map;
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/meta/Meta$Companion {
+	public static final field TYPE Ljava/lang/String;
+	public static final field VALUE_KEY Ljava/lang/String;
+	public final fun getEMPTY ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/meta/Meta$DefaultImpls {
+	public static fun getItem (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static fun toMeta (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Meta;
+}
+
+public abstract class hep/dataforge/meta/MetaBase : hep/dataforge/meta/Meta {
+	public fun <init> ()V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public fun hashCode ()I
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/meta/MetaBuilder : hep/dataforge/meta/AbstractMutableMeta {
+	public fun <init> ()V
+	public synthetic fun empty$dataforge_meta ()Lhep/dataforge/meta/MutableMeta;
+	public final fun put (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public final fun put (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaRepr;)V
+	public final fun put (Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
+	public final fun put (Lhep/dataforge/names/Name;Ljava/lang/Boolean;)V
+	public final fun put (Lhep/dataforge/names/Name;Ljava/lang/Enum;)V
+	public final fun put (Lhep/dataforge/names/Name;Ljava/lang/Number;)V
+	public final fun put (Lhep/dataforge/names/Name;Ljava/lang/String;)V
+	public final fun put (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/meta/MetaRepr;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/values/Value;)V
+	public final fun put (Ljava/lang/String;Ljava/lang/Boolean;)V
+	public final fun put (Ljava/lang/String;Ljava/lang/Enum;)V
+	public final fun put (Ljava/lang/String;Ljava/lang/Number;)V
+	public final fun put (Ljava/lang/String;Ljava/lang/String;)V
+	public final fun put (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public final fun put (Ljava/lang/String;[D)V
+	public final fun putMetas (Lhep/dataforge/names/Name;Ljava/lang/Iterable;)V
+	public final fun putMetas (Ljava/lang/String;Ljava/lang/Iterable;)V
+	public final fun putNumbers (Ljava/lang/String;Ljava/lang/Iterable;)V
+	public final fun putStrings (Ljava/lang/String;Ljava/lang/Iterable;)V
+	public final fun putValues (Lhep/dataforge/names/Name;Ljava/lang/Iterable;)V
+	public final fun putValues (Ljava/lang/String;Ljava/lang/Iterable;)V
+	public synthetic fun wrapNode (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MutableMeta;
+}
+
+public final class hep/dataforge/meta/MetaBuilderKt {
+	public static final fun Meta (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaBuilder;
+	public static final fun builder (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaBuilder;
+	public static final fun edit (Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaBuilder;
+}
+
+public abstract class hep/dataforge/meta/MetaItem {
+	public static final field Companion Lhep/dataforge/meta/MetaItem$Companion;
+	public abstract fun equals (Ljava/lang/Object;)Z
+	public abstract fun hashCode ()I
+}
+
+public final class hep/dataforge/meta/MetaItem$Companion {
+	public final fun of (Ljava/lang/Object;)Lhep/dataforge/meta/MetaItem;
+	public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/meta/MetaItem$NodeItem : hep/dataforge/meta/MetaItem {
+	public static final field Companion Lhep/dataforge/meta/MetaItem$NodeItem$Companion;
+	public fun <init> (Lhep/dataforge/meta/Meta;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getNode ()Lhep/dataforge/meta/Meta;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/meta/MetaItem$NodeItem$Companion {
+	public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/meta/MetaItem$ValueItem : hep/dataforge/meta/MetaItem {
+	public static final field Companion Lhep/dataforge/meta/MetaItem$ValueItem$Companion;
+	public fun <init> (Lhep/dataforge/values/Value;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getValue ()Lhep/dataforge/values/Value;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/meta/MetaItem$ValueItem$Companion {
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/meta/MetaItemSerializer : kotlinx/serialization/KSerializer {
+	public static final field INSTANCE Lhep/dataforge/meta/MetaItemSerializer;
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/MetaItem;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/meta/MetaItem;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/meta/MetaKt {
+	public static final fun asMetaItem (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaItem$NodeItem;
+	public static final fun asMetaItem (Lhep/dataforge/values/Value;)Lhep/dataforge/meta/MetaItem$ValueItem;
+	public static final fun get (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static final fun get (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
+	public static final fun get (Lhep/dataforge/meta/Meta;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
+	public static final fun get (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static final fun get (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
+	public static final fun get (Lhep/dataforge/meta/MetaNode;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
+	public static final fun getBoolean (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Boolean;
+	public static final fun getDouble (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Double;
+	public static final fun getFloat (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Float;
+	public static final fun getInt (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Integer;
+	public static final fun getLong (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Long;
+	public static final fun getNode (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/meta/Meta;
+	public static final fun getNumber (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Number;
+	public static final fun getShort (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Short;
+	public static final fun getString (Lhep/dataforge/meta/MetaItem;)Ljava/lang/String;
+	public static final fun getStringList (Lhep/dataforge/meta/MetaItem;)Ljava/util/List;
+	public static final fun getValue (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/values/Value;
+	public static final fun isEmpty (Lhep/dataforge/meta/Meta;)Z
+	public static final fun iterator (Lhep/dataforge/meta/Meta;)Ljava/util/Iterator;
+	public static final fun seal (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/SealedMeta;
+	public static final fun seal (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/meta/MetaItem;
+	public static final fun sequence (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+	public static final fun values (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+}
+
+public final class hep/dataforge/meta/MetaListener {
+	public fun <init> (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V
+	public synthetic fun <init> (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Ljava/lang/Object;
+	public final fun component2 ()Lkotlin/jvm/functions/Function3;
+	public final fun copy (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/meta/MetaListener;
+	public static synthetic fun copy$default (Lhep/dataforge/meta/MetaListener;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/meta/MetaListener;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getAction ()Lkotlin/jvm/functions/Function3;
+	public final fun getOwner ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public abstract interface class hep/dataforge/meta/MetaNode : hep/dataforge/meta/Meta {
+	public abstract fun getItems ()Ljava/util/Map;
+}
+
+public final class hep/dataforge/meta/MetaNode$DefaultImpls {
+	public static fun getItem (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static fun toMeta (Lhep/dataforge/meta/MetaNode;)Lhep/dataforge/meta/Meta;
+}
+
+public abstract interface class hep/dataforge/meta/MetaRepr {
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public class hep/dataforge/meta/MetaScheme : hep/dataforge/meta/Scheme {
+	public fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;Lhep/dataforge/meta/Config;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;Lhep/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getDefaultLayer ()Lhep/dataforge/meta/Meta;
+	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
+}
+
+public final class hep/dataforge/meta/MetaSerializer : kotlinx/serialization/KSerializer {
+	public static final field INSTANCE Lhep/dataforge/meta/MetaSerializer;
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/Meta;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/meta/MutableItemDelegateKt {
+	public static final fun boolean (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun boolean (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun boolean (Lhep/dataforge/meta/MutableItemProvider;ZLhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/MutableItemProvider;ZLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun convert (Lkotlin/properties/ReadWriteProperty;Lhep/dataforge/meta/transformations/MetaConverter;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun convert (Lkotlin/properties/ReadWriteProperty;Lhep/dataforge/meta/transformations/MetaConverter;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun convert (Lkotlin/properties/ReadWriteProperty;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun double (Lhep/dataforge/meta/MutableItemProvider;DLhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun double (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun double$default (Lhep/dataforge/meta/MutableItemProvider;DLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun double$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun doubleArray (Lhep/dataforge/meta/MutableItemProvider;[DLhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun doubleArray$default (Lhep/dataforge/meta/MutableItemProvider;[DLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun float (Lhep/dataforge/meta/MutableItemProvider;FLhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun float (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun float$default (Lhep/dataforge/meta/MutableItemProvider;FLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun float$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun int (Lhep/dataforge/meta/MutableItemProvider;ILhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun int (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun int$default (Lhep/dataforge/meta/MutableItemProvider;ILhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun int$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun item (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun item$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun listValue (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun listValue$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun long (Lhep/dataforge/meta/MutableItemProvider;JLhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun long (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun long$default (Lhep/dataforge/meta/MutableItemProvider;JLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun long$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun number (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun number (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun number (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/Number;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/Number;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun numberList (Lhep/dataforge/meta/MutableItemProvider;[Ljava/lang/Number;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun numberList$default (Lhep/dataforge/meta/MutableItemProvider;[Ljava/lang/Number;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun string (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun string (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun string (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun stringList (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun stringList (Lhep/dataforge/meta/MutableItemProvider;[Ljava/lang/String;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun stringList$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun stringList$default (Lhep/dataforge/meta/MutableItemProvider;[Ljava/lang/String;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun value (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun value (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun value (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun value$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun value$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun value$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+}
+
+public abstract interface class hep/dataforge/meta/MutableItemProvider : hep/dataforge/meta/ItemProvider {
+	public abstract fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
+}
+
+public abstract interface class hep/dataforge/meta/MutableMeta : hep/dataforge/meta/MetaNode, hep/dataforge/meta/MutableItemProvider {
+	public abstract fun getItems ()Ljava/util/Map;
+}
+
+public final class hep/dataforge/meta/MutableMeta$DefaultImpls {
+	public static fun getItem (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static fun toMeta (Lhep/dataforge/meta/MutableMeta;)Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/meta/MutableMetaKt {
+	public static final fun append (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
+	public static final fun append (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Object;)V
+	public static final fun edit (Lhep/dataforge/meta/AbstractMutableMeta;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
+	public static final fun remove (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;)V
+	public static final fun remove (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;)V
+	public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
+	public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;)V
+	public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
+	public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/NameToken;Ljava/lang/Object;)V
+	public static final fun set (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Iterable;)V
+	public static final fun set (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Object;)V
+	public static final fun set (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V
+	public static final fun setIndexed (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
+	public static synthetic fun setIndexed$default (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+	public static final fun setIndexedItems (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
+	public static synthetic fun setIndexedItems$default (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+	public static final fun setItem (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
+	public static final fun setNode (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public static final fun setNode (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
+	public static final fun setValue (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
+	public static final fun setValue (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Lhep/dataforge/values/Value;)V
+	public static final fun update (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/meta/Meta;)V
+}
+
+public abstract interface class hep/dataforge/meta/ObservableMeta : hep/dataforge/meta/Meta {
+	public abstract fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V
+	public abstract fun removeListener (Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/meta/ObservableMeta$DefaultImpls {
+	public static fun getItem (Lhep/dataforge/meta/ObservableMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static fun toMeta (Lhep/dataforge/meta/ObservableMeta;)Lhep/dataforge/meta/Meta;
+}
+
+public class hep/dataforge/meta/Scheme : hep/dataforge/meta/Configurable, hep/dataforge/meta/MetaRepr, hep/dataforge/meta/descriptors/Described {
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)V
+	public fun getConfig ()Lhep/dataforge/meta/Config;
+	public fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public fun getDefaultLayer ()Lhep/dataforge/meta/Meta;
+	public final fun getDefaultProvider ()Lhep/dataforge/meta/ItemProvider;
+	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
+	public fun toMeta ()Lhep/dataforge/meta/Laminate;
+	public synthetic fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+}
+
+public final class hep/dataforge/meta/SchemeKt {
+	public static final fun asScheme (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaScheme;
+	public static final fun invoke (Lhep/dataforge/meta/Scheme;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
+	public static final fun toScheme (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+	public static synthetic fun toScheme$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/Configurable;
+}
+
+public class hep/dataforge/meta/SchemeSpec : hep/dataforge/meta/Specification {
+	public fun <init> (Lkotlin/jvm/functions/Function0;)V
+	public fun <init> (Lkotlin/jvm/functions/Function2;)V
+	public synthetic fun empty ()Lhep/dataforge/meta/Configurable;
+	public fun empty ()Lhep/dataforge/meta/Scheme;
+	public synthetic fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+	public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
+	public synthetic fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Configurable;
+	public fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
+}
+
+public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractMetaNode {
+	public fun getItems ()Ljava/util/Map;
+}
+
+public abstract interface class hep/dataforge/meta/Specification {
+	public abstract fun empty ()Lhep/dataforge/meta/Configurable;
+	public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+	public abstract fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Configurable;
+}
+
+public final class hep/dataforge/meta/Specification$DefaultImpls {
+	public static fun empty (Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/Configurable;
+	public static fun invoke (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+	public static synthetic fun wrap$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/Configurable;
+}
+
+public final class hep/dataforge/meta/SpecificationKt {
+	public static final fun configSpec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/Configurable;
+	public static final fun configure (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+	public static final fun createStyle (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Meta;
+	public static final fun spec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/Configurable;
+	public static final fun update (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+	public static final fun update (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+	public static final fun wrap (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Configurable;
+}
+
+public abstract interface class hep/dataforge/meta/descriptors/Described {
+	public static final field Companion Lhep/dataforge/meta/descriptors/Described$Companion;
+	public abstract fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
+}
+
+public final class hep/dataforge/meta/descriptors/Described$Companion {
+}
+
+public final class hep/dataforge/meta/descriptors/DescriptorMetaKt {
+	public static final fun defaultItem (Lhep/dataforge/meta/descriptors/ItemDescriptor;)Lhep/dataforge/meta/MetaItem;
+	public static final fun defaultMeta (Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Laminate;
+}
+
+public abstract class hep/dataforge/meta/descriptors/ItemDescriptor {
+	public static final field Companion Lhep/dataforge/meta/descriptors/ItemDescriptor$Companion;
+	public static final field DEFAULT_INDEX_KEY Ljava/lang/String;
+	public synthetic fun <init> (Lhep/dataforge/meta/Config;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun getAttributes ()Lhep/dataforge/meta/Config;
+	public final fun getConfig ()Lhep/dataforge/meta/Config;
+	public final fun getIndexKey ()Ljava/lang/String;
+	public final fun getInfo ()Ljava/lang/String;
+	public final fun getMultiple ()Z
+	public abstract fun getRequired ()Z
+	public final fun setAttributes (Lhep/dataforge/meta/Config;)V
+	public final fun setIndexKey (Ljava/lang/String;)V
+	public final fun setInfo (Ljava/lang/String;)V
+	public final fun setMultiple (Z)V
+	public abstract fun setRequired (Z)V
+}
+
+public final class hep/dataforge/meta/descriptors/ItemDescriptor$Companion {
+}
+
+public final class hep/dataforge/meta/descriptors/ItemDescriptorKt {
+	public static final fun attributes (Lhep/dataforge/meta/descriptors/ItemDescriptor;Lkotlin/jvm/functions/Function1;)V
+	public static final fun get (Lhep/dataforge/meta/descriptors/ItemDescriptor;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public static final fun get (Lhep/dataforge/meta/descriptors/ItemDescriptor;Ljava/lang/String;)Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public static final fun plus (Lhep/dataforge/meta/descriptors/NodeDescriptor;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public static final fun validateItem (Lhep/dataforge/meta/descriptors/ItemDescriptor;Lhep/dataforge/meta/MetaItem;)Z
+}
+
+public final class hep/dataforge/meta/descriptors/NodeDescriptor : hep/dataforge/meta/descriptors/ItemDescriptor {
+	public static final field Companion Lhep/dataforge/meta/descriptors/NodeDescriptor$Companion;
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/meta/Config;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun getDefault ()Lhep/dataforge/meta/Config;
+	public final fun getItems ()Ljava/util/Map;
+	public final fun getNodes ()Ljava/util/Map;
+	public fun getRequired ()Z
+	public final fun getValues ()Ljava/util/Map;
+	public final fun item (Lhep/dataforge/names/Name;Lhep/dataforge/meta/descriptors/ItemDescriptor;)V
+	public final fun item (Ljava/lang/String;Lhep/dataforge/meta/descriptors/ItemDescriptor;)V
+	public final fun node (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
+	public final fun node (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public final fun setDefault (Lhep/dataforge/meta/Config;)V
+	public fun setRequired (Z)V
+	public final fun value (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
+	public final fun value (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+}
+
+public final class hep/dataforge/meta/descriptors/NodeDescriptor$Companion {
+	public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/descriptors/NodeDescriptor;
+}
+
+public final class hep/dataforge/meta/descriptors/ValueDescriptor : hep/dataforge/meta/descriptors/ItemDescriptor {
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/meta/Config;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun allow ([Ljava/lang/Object;)V
+	public final fun default (Ljava/lang/Object;)V
+	public final fun getAllowedValues ()Ljava/util/List;
+	public final fun getDefault ()Lhep/dataforge/values/Value;
+	public fun getRequired ()Z
+	public final fun getType ()Ljava/util/List;
+	public final fun isAllowedValue (Lhep/dataforge/values/Value;)Z
+	public final fun setAllowedValues (Ljava/util/List;)V
+	public final fun setDefault (Lhep/dataforge/values/Value;)V
+	public fun setRequired (Z)V
+	public final fun setType (Ljava/util/List;)V
+	public final fun type ([Lhep/dataforge/values/ValueType;)V
+}
+
+public final class hep/dataforge/meta/transformations/KeepTransformationRule : hep/dataforge/meta/transformations/TransformationRule {
+	public fun <init> (Lkotlin/jvm/functions/Function1;)V
+	public final fun component1 ()Lkotlin/jvm/functions/Function1;
+	public final fun copy (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/transformations/KeepTransformationRule;
+	public static synthetic fun copy$default (Lhep/dataforge/meta/transformations/KeepTransformationRule;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/transformations/KeepTransformationRule;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getSelector ()Lkotlin/jvm/functions/Function1;
+	public fun hashCode ()I
+	public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+	public fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+	public fun toString ()Ljava/lang/String;
+	public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
+}
+
+public abstract interface class hep/dataforge/meta/transformations/MetaConverter {
+	public static final field Companion Lhep/dataforge/meta/transformations/MetaConverter$Companion;
+	public abstract fun itemToObject (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Object;
+	public abstract fun objectToMetaItem (Ljava/lang/Object;)Lhep/dataforge/meta/MetaItem;
+}
+
+public final class hep/dataforge/meta/transformations/MetaConverter$Companion {
+	public final fun getBoolean ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getDouble ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getFloat ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getInt ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getItem ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getLong ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getMeta ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getNumber ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getString ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getValue ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun valueList (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/transformations/MetaConverter;
+	public static synthetic fun valueList$default (Lhep/dataforge/meta/transformations/MetaConverter$Companion;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/transformations/MetaConverter;
+}
+
+public final class hep/dataforge/meta/transformations/MetaConverterKt {
+	public static final fun metaToObject (Lhep/dataforge/meta/transformations/MetaConverter;Lhep/dataforge/meta/Meta;)Ljava/lang/Object;
+	public static final fun nullableItemToObject (Lhep/dataforge/meta/transformations/MetaConverter;Lhep/dataforge/meta/MetaItem;)Ljava/lang/Object;
+	public static final fun nullableObjectToMetaItem (Lhep/dataforge/meta/transformations/MetaConverter;Ljava/lang/Object;)Lhep/dataforge/meta/MetaItem;
+	public static final fun valueToObject (Lhep/dataforge/meta/transformations/MetaConverter;Lhep/dataforge/values/Value;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/meta/transformations/MetaTransformation {
+	public static final field Companion Lhep/dataforge/meta/transformations/MetaTransformation$Companion;
+	public static final fun apply-impl (Ljava/util/Collection;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Meta;
+	public static final fun bind-impl (Ljava/util/Collection;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/MutableMeta;)V
+	public static final synthetic fun box-impl (Ljava/util/Collection;)Lhep/dataforge/meta/transformations/MetaTransformation;
+	public static fun constructor-impl (Ljava/util/Collection;)Ljava/util/Collection;
+	public fun equals (Ljava/lang/Object;)Z
+	public static fun equals-impl (Ljava/util/Collection;Ljava/lang/Object;)Z
+	public static final fun equals-impl0 (Ljava/util/Collection;Ljava/util/Collection;)Z
+	public static final fun generate-impl (Ljava/util/Collection;Lhep/dataforge/meta/Config;)Lhep/dataforge/meta/ObservableMeta;
+	public static final fun generate-impl (Ljava/util/Collection;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Meta;
+	public final fun getTransformations ()Ljava/util/Collection;
+	public fun hashCode ()I
+	public static fun hashCode-impl (Ljava/util/Collection;)I
+	public fun toString ()Ljava/lang/String;
+	public static fun toString-impl (Ljava/util/Collection;)Ljava/lang/String;
+	public final synthetic fun unbox-impl ()Ljava/util/Collection;
+}
+
+public final class hep/dataforge/meta/transformations/MetaTransformation$Companion {
+	public final fun make-S5KKvQA (Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
+}
+
+public final class hep/dataforge/meta/transformations/MetaTransformationBuilder {
+	public fun <init> ()V
+	public final fun build-S5KKvQA ()Ljava/util/Collection;
+	public final fun keep (Lhep/dataforge/names/Name;)V
+	public final fun keep (Ljava/lang/String;)V
+	public final fun keep (Lkotlin/jvm/functions/Function1;)V
+	public final fun move (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
+	public static synthetic fun move$default (Lhep/dataforge/meta/transformations/MetaTransformationBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+}
+
+public final class hep/dataforge/meta/transformations/RegexItemTransformationRule : hep/dataforge/meta/transformations/TransformationRule {
+	public fun <init> (Lkotlin/text/Regex;Lkotlin/jvm/functions/Function4;)V
+	public final fun component1 ()Lkotlin/text/Regex;
+	public final fun component2 ()Lkotlin/jvm/functions/Function4;
+	public final fun copy (Lkotlin/text/Regex;Lkotlin/jvm/functions/Function4;)Lhep/dataforge/meta/transformations/RegexItemTransformationRule;
+	public static synthetic fun copy$default (Lhep/dataforge/meta/transformations/RegexItemTransformationRule;Lkotlin/text/Regex;Lkotlin/jvm/functions/Function4;ILjava/lang/Object;)Lhep/dataforge/meta/transformations/RegexItemTransformationRule;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getFrom ()Lkotlin/text/Regex;
+	public final fun getTransform ()Lkotlin/jvm/functions/Function4;
+	public fun hashCode ()I
+	public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+	public fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+	public fun toString ()Ljava/lang/String;
+	public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
+}
+
+public final class hep/dataforge/meta/transformations/SingleItemTransformationRule : hep/dataforge/meta/transformations/TransformationRule {
+	public fun <init> (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function3;)V
+	public final fun component1 ()Lhep/dataforge/names/Name;
+	public final fun component2 ()Lkotlin/jvm/functions/Function3;
+	public final fun copy (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/meta/transformations/SingleItemTransformationRule;
+	public static synthetic fun copy$default (Lhep/dataforge/meta/transformations/SingleItemTransformationRule;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/meta/transformations/SingleItemTransformationRule;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getFrom ()Lhep/dataforge/names/Name;
+	public final fun getTransform ()Lkotlin/jvm/functions/Function3;
+	public fun hashCode ()I
+	public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+	public fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+	public fun toString ()Ljava/lang/String;
+	public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
+}
+
+public abstract interface class hep/dataforge/meta/transformations/TransformationRule {
+	public abstract fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+	public abstract fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+	public abstract fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
+}
+
+public final class hep/dataforge/meta/transformations/TransformationRule$DefaultImpls {
+	public static fun selectItems (Lhep/dataforge/meta/transformations/TransformationRule;Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+}
+
+public final class hep/dataforge/names/Name {
+	public static final field Companion Lhep/dataforge/names/Name$Companion;
+	public static final field NAME_SEPARATOR Ljava/lang/String;
+	public fun <init> (Ljava/util/List;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getTokens ()Ljava/util/List;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/names/Name$Companion : kotlinx/serialization/KSerializer {
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/names/Name;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public final fun getEMPTY ()Lhep/dataforge/names/Name;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/names/Name;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/names/NameKt {
+	public static final fun appendLeft (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/names/Name;
+	public static final fun asName (Lhep/dataforge/names/NameToken;)Lhep/dataforge/names/Name;
+	public static final fun asName (Ljava/lang/String;)Lhep/dataforge/names/Name;
+	public static final fun cutFirst (Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
+	public static final fun cutLast (Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
+	public static final fun endsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Z
+	public static final fun endsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/NameToken;)Z
+	public static final fun firstOrNull (Lhep/dataforge/names/Name;)Lhep/dataforge/names/NameToken;
+	public static final fun get (Lhep/dataforge/names/Name;I)Lhep/dataforge/names/NameToken;
+	public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object;
+	public static final fun get (Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
+	public static synthetic fun get$default (Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/Object;
+	public static final fun getLength (Lhep/dataforge/names/Name;)I
+	public static final fun hasIndex (Lhep/dataforge/names/NameToken;)Z
+	public static final fun isEmpty (Lhep/dataforge/names/Name;)Z
+	public static final fun lastOrNull (Lhep/dataforge/names/Name;)Lhep/dataforge/names/NameToken;
+	public static final fun plus (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
+	public static final fun plus (Lhep/dataforge/names/Name;Lhep/dataforge/names/NameToken;)Lhep/dataforge/names/Name;
+	public static final fun plus (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/names/Name;
+	public static final fun plus (Lhep/dataforge/names/NameToken;Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
+	public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V
+	public static final fun startsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Z
+	public static final fun startsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/NameToken;)Z
+	public static final fun toName (Ljava/lang/String;)Lhep/dataforge/names/Name;
+	public static final fun withIndex (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/names/Name;
+	public static final fun withIndex (Lhep/dataforge/names/NameToken;Ljava/lang/String;)Lhep/dataforge/names/NameToken;
+}
+
+public final class hep/dataforge/names/NameToken {
+	public static final field Companion Lhep/dataforge/names/NameToken$Companion;
+	public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
+	public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Ljava/lang/String;
+	public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lhep/dataforge/names/NameToken;
+	public static synthetic fun copy$default (Lhep/dataforge/names/NameToken;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lhep/dataforge/names/NameToken;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getBody ()Ljava/lang/String;
+	public final fun getIndex ()Ljava/lang/String;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/names/NameToken$Companion : kotlinx/serialization/KSerializer {
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/names/NameToken;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/names/NameToken;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/values/DoubleArrayValue : hep/dataforge/values/Value {
+	public fun <init> ([D)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Double;
+	public synthetic fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public synthetic fun getValue ()Ljava/lang/Object;
+	public fun getValue ()[D
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/EnumValue : hep/dataforge/values/Value {
+	public fun <init> (Ljava/lang/Enum;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Enum;
+	public synthetic fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/ExoticValuesKt {
+	public static final fun asValue ([D)Lhep/dataforge/values/Value;
+	public static final fun lazyParseValue (Ljava/lang/String;)Lhep/dataforge/values/LazyParsedValue;
+}
+
+public final class hep/dataforge/values/False : hep/dataforge/values/Value {
+	public static final field INSTANCE Lhep/dataforge/values/False;
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/LazyParsedValue : hep/dataforge/values/Value {
+	public fun <init> (Ljava/lang/String;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/ListValue : hep/dataforge/values/Value {
+	public fun <init> (Ljava/util/List;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public synthetic fun getValue ()Ljava/lang/Object;
+	public fun getValue ()Ljava/util/List;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/Null : hep/dataforge/values/Value {
+	public static final field INSTANCE Lhep/dataforge/values/Null;
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/NumberValue : hep/dataforge/values/Value {
+	public fun <init> (Ljava/lang/Number;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/StringValue : hep/dataforge/values/Value {
+	public fun <init> (Ljava/lang/String;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/True : hep/dataforge/values/Value {
+	public static final field INSTANCE Lhep/dataforge/values/True;
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public abstract interface class hep/dataforge/values/Value {
+	public static final field Companion Lhep/dataforge/values/Value$Companion;
+	public static final field TARGET Ljava/lang/String;
+	public abstract fun equals (Ljava/lang/Object;)Z
+	public abstract fun getList ()Ljava/util/List;
+	public abstract fun getNumber ()Ljava/lang/Number;
+	public abstract fun getString ()Ljava/lang/String;
+	public abstract fun getType ()Lhep/dataforge/values/ValueType;
+	public abstract fun getValue ()Ljava/lang/Object;
+	public abstract fun hashCode ()I
+}
+
+public final class hep/dataforge/values/Value$Companion {
+	public static final field TARGET Ljava/lang/String;
+	public final fun of (Ljava/lang/Object;)Lhep/dataforge/values/Value;
+}
+
+public final class hep/dataforge/values/Value$DefaultImpls {
+	public static fun getList (Lhep/dataforge/values/Value;)Ljava/util/List;
+}
+
+public final class hep/dataforge/values/ValueExtensionsKt {
+	public static final fun getBoolean (Lhep/dataforge/values/Value;)Z
+	public static final fun getDouble (Lhep/dataforge/values/Value;)D
+	public static final fun getDoubleArray (Lhep/dataforge/values/Value;)[D
+	public static final fun getFloat (Lhep/dataforge/values/Value;)F
+	public static final fun getInt (Lhep/dataforge/values/Value;)I
+	public static final fun getLong (Lhep/dataforge/values/Value;)J
+	public static final fun getShort (Lhep/dataforge/values/Value;)S
+	public static final fun getStringList (Lhep/dataforge/values/Value;)Ljava/util/List;
+	public static final fun isList (Lhep/dataforge/values/Value;)Z
+	public static final fun isNull (Lhep/dataforge/values/Value;)Z
+	public static final fun toMeta (Lhep/dataforge/values/Value;)Lhep/dataforge/meta/MetaBuilder;
+}
+
+public final class hep/dataforge/values/ValueKt {
+	public static final fun asValue (Ljava/lang/Enum;)Lhep/dataforge/values/Value;
+	public static final fun asValue (Ljava/lang/Iterable;)Lhep/dataforge/values/Value;
+	public static final fun asValue (Ljava/lang/Number;)Lhep/dataforge/values/Value;
+	public static final fun asValue (Ljava/lang/String;)Lhep/dataforge/values/Value;
+	public static final fun asValue (Z)Lhep/dataforge/values/Value;
+	public static final fun asValue ([B)Lhep/dataforge/values/Value;
+	public static final fun asValue ([F)Lhep/dataforge/values/Value;
+	public static final fun asValue ([I)Lhep/dataforge/values/Value;
+	public static final fun asValue ([J)Lhep/dataforge/values/Value;
+	public static final fun asValue ([S)Lhep/dataforge/values/Value;
+	public static final fun parseValue (Ljava/lang/String;)Lhep/dataforge/values/Value;
+}
+
+public final class hep/dataforge/values/ValueSerializer : kotlinx/serialization/KSerializer {
+	public static final field INSTANCE Lhep/dataforge/values/ValueSerializer;
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/values/Value;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/values/Value;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/values/ValueType : java/lang/Enum {
+	public static final field BOOLEAN Lhep/dataforge/values/ValueType;
+	public static final field Companion Lhep/dataforge/values/ValueType$Companion;
+	public static final field NULL Lhep/dataforge/values/ValueType;
+	public static final field NUMBER Lhep/dataforge/values/ValueType;
+	public static final field STRING Lhep/dataforge/values/ValueType;
+	public static fun valueOf (Ljava/lang/String;)Lhep/dataforge/values/ValueType;
+	public static fun values ()[Lhep/dataforge/values/ValueType;
+}
+
+public final class hep/dataforge/values/ValueType$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
+	public static final field INSTANCE Lhep/dataforge/values/ValueType$$serializer;
+	public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/values/ValueType;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/values/ValueType;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+	public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/values/ValueType$Companion {
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
+}
+
diff --git a/dataforge-output/api/dataforge-output.api b/dataforge-output/api/dataforge-output.api
new file mode 100644
index 00000000..f991b754
--- /dev/null
+++ b/dataforge-output/api/dataforge-output.api
@@ -0,0 +1,68 @@
+public final class hep/dataforge/output/ConsoleOutputManager : hep/dataforge/context/AbstractPlugin, hep/dataforge/output/OutputManager {
+	public static final field Companion Lhep/dataforge/output/ConsoleOutputManager$Companion;
+	public fun <init> ()V
+	public fun get (Lkotlin/reflect/KClass;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)Lhep/dataforge/output/Renderer;
+	public fun getTag ()Lhep/dataforge/context/PluginTag;
+}
+
+public final class hep/dataforge/output/ConsoleOutputManager$Companion : hep/dataforge/context/PluginFactory {
+	public fun getTag ()Lhep/dataforge/context/PluginTag;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/output/ConsoleOutputManager;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/output/DefaultTextFormat : hep/dataforge/output/TextFormat {
+	public static final field INSTANCE Lhep/dataforge/output/DefaultTextFormat;
+	public fun getPriority ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun render (Ljava/lang/Appendable;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/output/OutputJVMKt {
+	public static final fun getOutput (Lkotlinx/coroutines/Dispatchers;)Lkotlinx/coroutines/CoroutineDispatcher;
+}
+
+public abstract interface class hep/dataforge/output/OutputManager {
+	public abstract fun get (Lkotlin/reflect/KClass;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)Lhep/dataforge/output/Renderer;
+}
+
+public final class hep/dataforge/output/OutputManager$DefaultImpls {
+	public static synthetic fun get$default (Lhep/dataforge/output/OutputManager;Lkotlin/reflect/KClass;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/output/Renderer;
+}
+
+public final class hep/dataforge/output/OutputManagerKt {
+	public static final fun getCONSOLE_RENDERER ()Lhep/dataforge/output/Renderer;
+	public static final fun getOutput (Lhep/dataforge/context/Context;)Lhep/dataforge/output/OutputManager;
+	public static final fun render (Lhep/dataforge/output/OutputManager;Ljava/lang/Object;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public static synthetic fun render$default (Lhep/dataforge/output/OutputManager;Ljava/lang/Object;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
+}
+
+public abstract interface class hep/dataforge/output/Renderer : hep/dataforge/context/ContextAware {
+	public abstract fun render (Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
+}
+
+public final class hep/dataforge/output/Renderer$DefaultImpls {
+	public static fun getLogger (Lhep/dataforge/output/Renderer;)Lmu/KLogger;
+	public static synthetic fun render$default (Lhep/dataforge/output/Renderer;Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
+}
+
+public abstract interface class hep/dataforge/output/TextFormat {
+	public static final field Companion Lhep/dataforge/output/TextFormat$Companion;
+	public static final field TEXT_RENDERER_TYPE Ljava/lang/String;
+	public abstract fun getPriority ()I
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun render (Ljava/lang/Appendable;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/output/TextFormat$Companion {
+	public static final field TEXT_RENDERER_TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/output/TextRenderer : hep/dataforge/output/Renderer {
+	public fun <init> (Lhep/dataforge/context/Context;Ljava/lang/Appendable;)V
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getLogger ()Lmu/KLogger;
+	public fun render (Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
+}
+
diff --git a/dataforge-output/dataforge-output-html/api/dataforge-output-html.api b/dataforge-output/dataforge-output-html/api/dataforge-output-html.api
new file mode 100644
index 00000000..964c6971
--- /dev/null
+++ b/dataforge-output/dataforge-output-html/api/dataforge-output-html.api
@@ -0,0 +1,26 @@
+public final class hep/dataforge/output/html/DefaultHtmlBuilder : hep/dataforge/output/html/HtmlBuilder {
+	public static final field INSTANCE Lhep/dataforge/output/html/DefaultHtmlBuilder;
+	public fun getPriority ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun render (Lkotlinx/html/FlowContent;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public abstract interface class hep/dataforge/output/html/HtmlBuilder {
+	public static final field Companion Lhep/dataforge/output/html/HtmlBuilder$Companion;
+	public static final field HTML_CONVERTER_TYPE Ljava/lang/String;
+	public abstract fun getPriority ()I
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun render (Lkotlinx/html/FlowContent;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/output/html/HtmlBuilder$Companion {
+	public static final field HTML_CONVERTER_TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/output/html/HtmlRenderer : hep/dataforge/output/Renderer {
+	public fun <init> (Lhep/dataforge/context/Context;Lkotlinx/html/TagConsumer;)V
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getLogger ()Lmu/KLogger;
+	public fun render (Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
+}
+
diff --git a/dataforge-scripting/api/dataforge-scripting.api b/dataforge-scripting/api/dataforge-scripting.api
new file mode 100644
index 00000000..b41aa156
--- /dev/null
+++ b/dataforge-scripting/api/dataforge-scripting.api
@@ -0,0 +1,6 @@
+public final class hep/dataforge/scripting/Builders {
+	public static final field INSTANCE Lhep/dataforge/scripting/Builders;
+	public final fun buildWorkspace (Ljava/io/File;)Lhep/dataforge/workspace/Workspace;
+	public final fun buildWorkspace (Ljava/lang/String;)Lhep/dataforge/workspace/Workspace;
+}
+
diff --git a/dataforge-tables/api/dataforge-tables.api b/dataforge-tables/api/dataforge-tables.api
new file mode 100644
index 00000000..e037773a
--- /dev/null
+++ b/dataforge-tables/api/dataforge-tables.api
@@ -0,0 +1,302 @@
+public final class hep/dataforge/tables/CachedTransformationColumn : hep/dataforge/tables/Column {
+	public fun <init> (Lhep/dataforge/tables/Table;Lkotlin/reflect/KClass;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)V
+	public fun get (I)Ljava/lang/Object;
+	public final fun getMapper ()Lkotlin/jvm/functions/Function1;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getSize ()I
+	public final fun getTable ()Lhep/dataforge/tables/Table;
+	public fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/tables/CastColumn : hep/dataforge/tables/Column {
+	public fun <init> (Lhep/dataforge/tables/Column;Lkotlin/reflect/KClass;)V
+	public fun get (I)Ljava/lang/Object;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public final fun getOrigin ()Lhep/dataforge/tables/Column;
+	public fun getSize ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/tables/CastColumnKt {
+	public static final fun cast (Lhep/dataforge/tables/Column;Lkotlin/reflect/KClass;)Lhep/dataforge/tables/Column;
+	public static final fun get (Ljava/util/Collection;Lhep/dataforge/tables/ColumnHeader;)Lhep/dataforge/tables/Column;
+}
+
+public abstract interface class hep/dataforge/tables/Column : hep/dataforge/tables/ColumnHeader {
+	public abstract fun get (I)Ljava/lang/Object;
+	public abstract fun getSize ()I
+}
+
+public final class hep/dataforge/tables/ColumnDef : hep/dataforge/tables/ColumnHeader {
+	public fun <init> (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Lkotlin/reflect/KClass;
+	public final fun component3 ()Lhep/dataforge/meta/Meta;
+	public final fun copy (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)Lhep/dataforge/tables/ColumnDef;
+	public static synthetic fun copy$default (Lhep/dataforge/tables/ColumnDef;Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/tables/ColumnDef;
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public abstract interface class hep/dataforge/tables/ColumnHeader {
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getName ()Ljava/lang/String;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/tables/ColumnHeaderKt {
+	public static final fun getTextWidth (Lhep/dataforge/tables/ColumnHeader;)I
+	public static final fun getValueType (Lhep/dataforge/tables/ColumnHeader;)Lhep/dataforge/values/ValueType;
+}
+
+public final class hep/dataforge/tables/ColumnProperty : kotlin/properties/ReadOnlyProperty {
+	public fun <init> (Lhep/dataforge/tables/Table;Lkotlin/reflect/KClass;)V
+	public final fun getTable ()Lhep/dataforge/tables/Table;
+	public final fun getType ()Lkotlin/reflect/KClass;
+	public fun getValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;)Lhep/dataforge/tables/Column;
+	public synthetic fun getValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;)Ljava/lang/Object;
+}
+
+public class hep/dataforge/tables/ColumnScheme : hep/dataforge/meta/Scheme {
+	public static final field Companion Lhep/dataforge/tables/ColumnScheme$Companion;
+	public fun <init> ()V
+	public final fun getTitle ()Ljava/lang/String;
+	public final fun setTitle (Ljava/lang/String;)V
+}
+
+public final class hep/dataforge/tables/ColumnScheme$Companion : hep/dataforge/meta/SchemeSpec {
+}
+
+public final class hep/dataforge/tables/ColumnTable : hep/dataforge/tables/Table {
+	public fun <init> (Ljava/util/Collection;)V
+	public fun getColumns ()Ljava/util/Collection;
+	public fun getHeader ()Ljava/util/List;
+	public fun getRows ()Ljava/util/List;
+	public fun getValue (ILjava/lang/String;)Ljava/lang/Object;
+	public fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/IntColumn : hep/dataforge/tables/Column {
+	public static final field Companion Lhep/dataforge/tables/IntColumn$Companion;
+	public fun <init> (Ljava/lang/String;[ILhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Ljava/lang/String;[ILhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun get (I)Ljava/lang/Integer;
+	public synthetic fun get (I)Ljava/lang/Object;
+	public final fun getData ()[I
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getSize ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun hashCode ()I
+}
+
+public final class hep/dataforge/tables/IntColumn$Companion {
+}
+
+public final class hep/dataforge/tables/ListColumn : hep/dataforge/tables/Column {
+	public static final field Companion Lhep/dataforge/tables/ListColumn$Companion;
+	public fun <init> (Ljava/lang/String;Ljava/util/List;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)V
+	public fun get (I)Ljava/lang/Object;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getSize ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/tables/ListColumn$Companion {
+}
+
+public final class hep/dataforge/tables/MapRow : hep/dataforge/tables/Row {
+	public static final synthetic fun box-impl (Ljava/util/Map;)Lhep/dataforge/tables/MapRow;
+	public static fun constructor-impl (Ljava/util/Map;)Ljava/util/Map;
+	public fun equals (Ljava/lang/Object;)Z
+	public static fun equals-impl (Ljava/util/Map;Ljava/lang/Object;)Z
+	public static final fun equals-impl0 (Ljava/util/Map;Ljava/util/Map;)Z
+	public fun getValue (Ljava/lang/String;)Ljava/lang/Object;
+	public static fun getValue-impl (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object;
+	public fun hashCode ()I
+	public static fun hashCode-impl (Ljava/util/Map;)I
+	public fun toString ()Ljava/lang/String;
+	public static fun toString-impl (Ljava/util/Map;)Ljava/lang/String;
+	public final synthetic fun unbox-impl ()Ljava/util/Map;
+}
+
+public final class hep/dataforge/tables/MutableColumnTable : hep/dataforge/tables/Table {
+	public fun <init> (I)V
+	public final fun add (Lhep/dataforge/tables/Column;)V
+	public synthetic fun getColumns ()Ljava/util/Collection;
+	public fun getColumns ()Ljava/util/List;
+	public fun getHeader ()Ljava/util/List;
+	public fun getRows ()Ljava/util/List;
+	public final fun getSize ()I
+	public fun getValue (ILjava/lang/String;)Ljava/lang/Object;
+	public final fun insert (ILhep/dataforge/tables/Column;)V
+	public fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/MutableTable : hep/dataforge/tables/RowTable {
+	public fun <init> (Ljava/util/List;Ljava/util/List;)V
+	public final fun column (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)Lhep/dataforge/tables/ColumnHeader;
+	public fun getHeader ()Ljava/util/List;
+	public fun getRows ()Ljava/util/List;
+	public final fun row (Ljava/util/Map;)Lhep/dataforge/tables/Row;
+	public final fun row ([Lkotlin/Pair;)Lhep/dataforge/tables/Row;
+}
+
+public final class hep/dataforge/tables/MutableTableKt {
+	public static final fun edit (Lhep/dataforge/tables/Table;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/tables/Table;
+	public static final fun row (Lhep/dataforge/tables/MutableTable;[Lkotlin/Pair;)Lhep/dataforge/tables/Row;
+}
+
+public final class hep/dataforge/tables/RealColumn : hep/dataforge/tables/Column {
+	public static final field Companion Lhep/dataforge/tables/RealColumn$Companion;
+	public fun <init> (Ljava/lang/String;[DLhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Ljava/lang/String;[DLhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun get (I)Ljava/lang/Double;
+	public synthetic fun get (I)Ljava/lang/Object;
+	public final fun getData ()[D
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getSize ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun hashCode ()I
+}
+
+public final class hep/dataforge/tables/RealColumn$Companion {
+}
+
+public abstract interface class hep/dataforge/tables/Row {
+	public abstract fun getValue (Ljava/lang/String;)Ljava/lang/Object;
+}
+
+public class hep/dataforge/tables/RowTable : hep/dataforge/tables/Table {
+	public fun <init> (Ljava/util/List;Ljava/util/List;)V
+	public synthetic fun getColumns ()Ljava/util/Collection;
+	public fun getColumns ()Ljava/util/List;
+	public fun getHeader ()Ljava/util/List;
+	public fun getRows ()Ljava/util/List;
+	public fun getValue (ILjava/lang/String;)Ljava/lang/Object;
+	public fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/RowTableKt {
+	public static final fun collect (Lhep/dataforge/tables/Rows;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public abstract interface class hep/dataforge/tables/Rows {
+	public abstract fun getHeader ()Ljava/util/List;
+	public abstract fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/SimpleColumnHeader : hep/dataforge/tables/ColumnHeader {
+	public fun <init> (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Lkotlin/reflect/KClass;
+	public final fun component3 ()Lhep/dataforge/meta/Meta;
+	public final fun copy (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)Lhep/dataforge/tables/SimpleColumnHeader;
+	public static synthetic fun copy$default (Lhep/dataforge/tables/SimpleColumnHeader;Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/tables/SimpleColumnHeader;
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public abstract interface class hep/dataforge/tables/Table : hep/dataforge/tables/Rows {
+	public static final field Companion Lhep/dataforge/tables/Table$Companion;
+	public abstract fun getColumns ()Ljava/util/Collection;
+	public abstract fun getHeader ()Ljava/util/List;
+	public abstract fun getRows ()Ljava/util/List;
+	public abstract fun getValue (ILjava/lang/String;)Ljava/lang/Object;
+	public abstract fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/Table$Companion {
+	public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/tables/Table;
+}
+
+public final class hep/dataforge/tables/Table$DefaultImpls {
+	public static fun getHeader (Lhep/dataforge/tables/Table;)Ljava/util/List;
+	public static fun rowFlow (Lhep/dataforge/tables/Table;)Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/TableKt {
+	public static final fun get (Lhep/dataforge/tables/Row;Lhep/dataforge/tables/ColumnHeader;)Ljava/lang/Object;
+	public static final fun get (Lhep/dataforge/tables/Table;ILhep/dataforge/tables/ColumnHeader;)Ljava/lang/Object;
+	public static final fun get (Ljava/util/Collection;Ljava/lang/String;)Lhep/dataforge/tables/Column;
+	public static final fun getIndices (Lhep/dataforge/tables/Column;)Lkotlin/ranges/IntRange;
+	public static final fun getValue (Lhep/dataforge/tables/Row;Ljava/lang/String;Lkotlin/reflect/KClass;)Ljava/lang/Object;
+	public static final fun getValue (Lhep/dataforge/tables/Table;ILjava/lang/String;Lkotlin/reflect/KClass;)Ljava/lang/Object;
+	public static final fun iterator (Lhep/dataforge/tables/Column;)Ljava/util/Iterator;
+}
+
+public final class hep/dataforge/tables/TransformationColumn : hep/dataforge/tables/Column {
+	public fun <init> (Lhep/dataforge/tables/Table;Lkotlin/reflect/KClass;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)V
+	public fun get (I)Ljava/lang/Object;
+	public final fun getMapper ()Lkotlin/jvm/functions/Function1;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getSize ()I
+	public final fun getTable ()Lhep/dataforge/tables/Table;
+	public fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/tables/TransformationColumnKt {
+	public static final fun mapRowsToDouble (Lhep/dataforge/tables/Table;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/tables/RealColumn;
+	public static synthetic fun mapRowsToDouble$default (Lhep/dataforge/tables/Table;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/tables/RealColumn;
+	public static final fun mapRowsToInt (Lhep/dataforge/tables/Table;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/tables/IntColumn;
+	public static synthetic fun mapRowsToInt$default (Lhep/dataforge/tables/Table;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/tables/IntColumn;
+}
+
+public final class hep/dataforge/tables/ValueColumnScheme : hep/dataforge/tables/ColumnScheme {
+	public fun <init> ()V
+	public final fun getValueType ()Lhep/dataforge/values/ValueType;
+	public final fun setValueType (Lhep/dataforge/values/ValueType;)V
+}
+
+public final class hep/dataforge/tables/io/TextRows : hep/dataforge/tables/Rows {
+	public static final field Companion Lhep/dataforge/tables/io/TextRows$Companion;
+	public fun <init> (Ljava/util/List;Lkotlinx/io/Binary;)V
+	public fun getHeader ()Ljava/util/List;
+	public final fun indexFlow ()Lkotlinx/coroutines/flow/Flow;
+	public fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/io/TextRows$Companion {
+}
+
+public final class hep/dataforge/tables/io/TextRowsKt {
+	public static final fun buildRowIndex (Lhep/dataforge/tables/io/TextRows;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+	public static final fun writeRows (Lkotlinx/io/Output;Lhep/dataforge/tables/Rows;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/tables/io/TextTable : hep/dataforge/tables/Table {
+	public static final field Companion Lhep/dataforge/tables/io/TextTable$Companion;
+	public fun <init> (Ljava/util/List;Lkotlinx/io/Binary;Ljava/util/List;)V
+	public fun getColumns ()Ljava/util/Collection;
+	public fun getHeader ()Ljava/util/List;
+	public final fun getIndex ()Ljava/util/List;
+	public fun getRows ()Ljava/util/List;
+	public fun getValue (ILjava/lang/String;)Lhep/dataforge/values/Value;
+	public synthetic fun getValue (ILjava/lang/String;)Ljava/lang/Object;
+	public fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/io/TextTable$Companion {
+	public final fun invoke (Ljava/util/List;Lkotlinx/io/Binary;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/tables/io/TextTableEnvelopeKt {
+	public static final fun readEnvelope (Lhep/dataforge/tables/io/TextRows$Companion;Lhep/dataforge/io/Envelope;)Lhep/dataforge/tables/io/TextRows;
+	public static final fun wrap (Lhep/dataforge/tables/Table;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
diff --git a/dataforge-workspace/api/dataforge-workspace.api b/dataforge-workspace/api/dataforge-workspace.api
new file mode 100644
index 00000000..c410f094
--- /dev/null
+++ b/dataforge-workspace/api/dataforge-workspace.api
@@ -0,0 +1,273 @@
+public final class hep/dataforge/workspace/AllDataDependency : hep/dataforge/workspace/Dependency {
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/names/Name;)V
+	public synthetic fun <init> (Lhep/dataforge/names/Name;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun apply (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/data/DataNode;
+	public synthetic fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun toMeta ()Lhep/dataforge/meta/MetaBuilder;
+}
+
+public final class hep/dataforge/workspace/DataDependency : hep/dataforge/workspace/Dependency {
+	public fun <init> (Lhep/dataforge/data/DataFilter;Lhep/dataforge/names/Name;)V
+	public synthetic fun <init> (Lhep/dataforge/data/DataFilter;Lhep/dataforge/names/Name;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun apply (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/data/DataNode;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public abstract class hep/dataforge/workspace/Dependency : hep/dataforge/meta/MetaRepr {
+	public abstract fun apply (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/data/DataNode;
+}
+
+public final class hep/dataforge/workspace/DirectTaskDependency : hep/dataforge/workspace/TaskDependency {
+	public static final field Companion Lhep/dataforge/workspace/DirectTaskDependency$Companion;
+	public fun <init> (Lhep/dataforge/workspace/Task;Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)V
+	public fun getName ()Lhep/dataforge/names/Name;
+	public final fun getTask ()Lhep/dataforge/workspace/Task;
+	public fun resolveTask (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/workspace/Task;
+}
+
+public final class hep/dataforge/workspace/DirectTaskDependency$Companion {
+	public final fun getDIRECT_TASK_NAME ()Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/workspace/EnvelopeDataKt {
+	public static final fun toData (Lhep/dataforge/io/Envelope;Lkotlin/reflect/KClass;Lhep/dataforge/io/IOFormat;)Lhep/dataforge/data/Data;
+	public static final fun toEnvelope (Lhep/dataforge/data/Data;Lhep/dataforge/io/IOFormat;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/workspace/FileDataKt {
+	public static final fun file (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lkotlin/jvm/functions/Function2;)V
+	public static final fun readDataDirectory (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/DataNode;
+	public static final fun readDataFile (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/Data;
+	public static final fun writeDataDirectory (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/data/DataNode;Lhep/dataforge/io/IOFormat;Lhep/dataforge/io/EnvelopeFormat;Lhep/dataforge/io/MetaFormatFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+	public static synthetic fun writeDataDirectory$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/data/DataNode;Lhep/dataforge/io/IOFormat;Lhep/dataforge/io/EnvelopeFormat;Lhep/dataforge/io/MetaFormatFactory;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
+	public static final fun writeZip (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/data/DataNode;Lhep/dataforge/io/IOFormat;Lhep/dataforge/io/EnvelopeFormat;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+	public static synthetic fun writeZip$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/data/DataNode;Lhep/dataforge/io/IOFormat;Lhep/dataforge/io/EnvelopeFormat;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/workspace/GenericTask : hep/dataforge/workspace/Task {
+	public fun <init> (Lhep/dataforge/names/Name;Lkotlin/reflect/KClass;Lhep/dataforge/meta/descriptors/NodeDescriptor;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)V
+	public fun build (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/TaskModel;
+	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun isTerminal ()Z
+	public fun run (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/TaskModel;)Lhep/dataforge/data/DataNode;
+	public fun validate (Lhep/dataforge/workspace/TaskModel;)V
+}
+
+public final class hep/dataforge/workspace/SimpleWorkspace : hep/dataforge/workspace/Workspace {
+	public static final field Companion Lhep/dataforge/workspace/SimpleWorkspace$Companion;
+	public fun <init> (Lhep/dataforge/context/Context;Lhep/dataforge/data/DataNode;Ljava/util/Map;Ljava/util/Collection;)V
+	public fun content (Ljava/lang/String;)Ljava/util/Map;
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getData ()Lhep/dataforge/data/DataNode;
+	public fun getDefaultChainTarget ()Ljava/lang/String;
+	public fun getDefaultTarget ()Ljava/lang/String;
+	public fun getLogger ()Lmu/KLogger;
+	public fun getTargets ()Ljava/util/Map;
+	public fun getTasks ()Ljava/util/Map;
+	public fun run (Lhep/dataforge/workspace/Task;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+}
+
+public final class hep/dataforge/workspace/SimpleWorkspace$Companion {
+}
+
+public final class hep/dataforge/workspace/SimpleWorkspaceBuilder : hep/dataforge/workspace/WorkspaceBuilder {
+	public fun <init> (Lhep/dataforge/context/Context;)V
+	public fun build ()Lhep/dataforge/workspace/SimpleWorkspace;
+	public synthetic fun build ()Lhep/dataforge/workspace/Workspace;
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getData ()Lhep/dataforge/data/DataTreeBuilder;
+	public fun getParentContext ()Lhep/dataforge/context/Context;
+	public fun getTargets ()Ljava/util/Map;
+	public fun getTasks ()Ljava/util/Set;
+	public fun setContext (Lhep/dataforge/context/Context;)V
+	public fun setData (Lhep/dataforge/data/DataTreeBuilder;)V
+	public fun setTargets (Ljava/util/Map;)V
+	public fun setTasks (Ljava/util/Set;)V
+}
+
+public abstract interface class hep/dataforge/workspace/Task : hep/dataforge/context/Named, hep/dataforge/meta/descriptors/Described {
+	public static final field Companion Lhep/dataforge/workspace/Task$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public abstract fun build (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/TaskModel;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun isTerminal ()Z
+	public abstract fun run (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/TaskModel;)Lhep/dataforge/data/DataNode;
+	public abstract fun validate (Lhep/dataforge/workspace/TaskModel;)V
+}
+
+public final class hep/dataforge/workspace/Task$Companion {
+	public static final field TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/workspace/Task$DefaultImpls {
+	public static fun isTerminal (Lhep/dataforge/workspace/Task;)Z
+	public static fun validate (Lhep/dataforge/workspace/Task;Lhep/dataforge/workspace/TaskModel;)V
+}
+
+public final class hep/dataforge/workspace/TaskBuilder {
+	public fun <init> (Lhep/dataforge/names/Name;Lkotlin/reflect/KClass;)V
+	public final fun description (Lkotlin/jvm/functions/Function1;)V
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getType ()Lkotlin/reflect/KClass;
+	public final fun model (Lkotlin/jvm/functions/Function2;)V
+	public final fun rawTransform (Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)V
+	public static synthetic fun rawTransform$default (Lhep/dataforge/workspace/TaskBuilder;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+	public final fun transform (Lkotlin/reflect/KClass;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)V
+	public static synthetic fun transform$default (Lhep/dataforge/workspace/TaskBuilder;Lkotlin/reflect/KClass;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+}
+
+public final class hep/dataforge/workspace/TaskBuilder$TaskEnv {
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;Lhep/dataforge/data/DataNode;)V
+	public final fun getContext ()Lhep/dataforge/context/Context;
+	public final fun getData ()Lhep/dataforge/data/DataNode;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun invoke (Lhep/dataforge/workspace/DirectTaskDependency;)Lhep/dataforge/data/DataNode;
+}
+
+public abstract class hep/dataforge/workspace/TaskDependency : hep/dataforge/workspace/Dependency {
+	public fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun apply (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/data/DataNode;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getName ()Lhep/dataforge/names/Name;
+	public final fun getPlacement ()Lhep/dataforge/names/Name;
+	public abstract fun resolveTask (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/workspace/Task;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public abstract interface class hep/dataforge/workspace/TaskDependencyContainer {
+	public abstract fun add (Lhep/dataforge/workspace/Dependency;)V
+	public abstract fun getDefaultMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/workspace/TaskModel : hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/workspace/TaskModel$Companion;
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Ljava/util/Collection;)V
+	public final fun component1 ()Lhep/dataforge/names/Name;
+	public final fun component2 ()Lhep/dataforge/meta/Meta;
+	public final fun component3 ()Ljava/util/Collection;
+	public final fun copy (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Ljava/util/Collection;)Lhep/dataforge/workspace/TaskModel;
+	public static synthetic fun copy$default (Lhep/dataforge/workspace/TaskModel;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Ljava/util/Collection;ILjava/lang/Object;)Lhep/dataforge/workspace/TaskModel;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getDependencies ()Ljava/util/Collection;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public fun hashCode ()I
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/workspace/TaskModel$Companion {
+	public final fun getMODEL_TARGET_KEY ()Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/workspace/TaskModelBuilder : hep/dataforge/workspace/TaskDependencyContainer {
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun add (Lhep/dataforge/workspace/Dependency;)V
+	public final fun build ()Lhep/dataforge/workspace/TaskModel;
+	public fun getDefaultMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getMeta ()Lhep/dataforge/meta/MetaBuilder;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getTarget ()Ljava/lang/String;
+	public final fun setMeta (Lhep/dataforge/meta/MetaBuilder;)V
+	public final fun setTarget (Ljava/lang/String;)V
+}
+
+public final class hep/dataforge/workspace/TaskModelKt {
+	public static final fun allData (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/names/Name;)Lhep/dataforge/workspace/AllDataDependency;
+	public static synthetic fun allData$default (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lhep/dataforge/workspace/AllDataDependency;
+	public static final fun buildInput (Lhep/dataforge/workspace/TaskModel;Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/data/DataTree;
+	public static final fun data (Lhep/dataforge/workspace/TaskDependencyContainer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lhep/dataforge/workspace/DataDependency;
+	public static final fun data (Lhep/dataforge/workspace/TaskDependencyContainer;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/DataDependency;
+	public static synthetic fun data$default (Lhep/dataforge/workspace/TaskDependencyContainer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lhep/dataforge/workspace/DataDependency;
+	public static final fun dependsOn (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/WorkspaceTaskDependency;
+	public static final fun dependsOn (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static final fun dependsOn (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static final fun dependsOn (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Ljava/lang/String;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static final fun dependsOn (Lhep/dataforge/workspace/TaskDependencyContainer;Ljava/lang/String;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/WorkspaceTaskDependency;
+	public static synthetic fun dependsOn$default (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/workspace/WorkspaceTaskDependency;
+	public static synthetic fun dependsOn$default (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static synthetic fun dependsOn$default (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static synthetic fun dependsOn$default (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Ljava/lang/String;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static synthetic fun dependsOn$default (Lhep/dataforge/workspace/TaskDependencyContainer;Ljava/lang/String;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/workspace/WorkspaceTaskDependency;
+	public static final fun getTarget (Lhep/dataforge/workspace/TaskModel;)Ljava/lang/String;
+}
+
+public abstract interface class hep/dataforge/workspace/Workspace : hep/dataforge/context/ContextAware, hep/dataforge/provider/Provider {
+	public static final field Companion Lhep/dataforge/workspace/Workspace$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public abstract fun content (Ljava/lang/String;)Ljava/util/Map;
+	public abstract fun getData ()Lhep/dataforge/data/DataNode;
+	public abstract fun getTargets ()Ljava/util/Map;
+	public abstract fun getTasks ()Ljava/util/Map;
+	public abstract fun run (Lhep/dataforge/workspace/Task;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+}
+
+public final class hep/dataforge/workspace/Workspace$Companion {
+	public static final field TYPE Ljava/lang/String;
+	public final fun invoke (Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/SimpleWorkspace;
+	public static synthetic fun invoke$default (Lhep/dataforge/workspace/Workspace$Companion;Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/workspace/SimpleWorkspace;
+}
+
+public final class hep/dataforge/workspace/Workspace$DefaultImpls {
+	public static fun content (Lhep/dataforge/workspace/Workspace;Ljava/lang/String;)Ljava/util/Map;
+	public static fun getDefaultChainTarget (Lhep/dataforge/workspace/Workspace;)Ljava/lang/String;
+	public static fun getDefaultTarget (Lhep/dataforge/workspace/Workspace;)Ljava/lang/String;
+	public static fun getLogger (Lhep/dataforge/workspace/Workspace;)Lmu/KLogger;
+	public static fun run (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/Task;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+}
+
+public abstract interface class hep/dataforge/workspace/WorkspaceBuilder {
+	public abstract fun build ()Lhep/dataforge/workspace/Workspace;
+	public abstract fun getContext ()Lhep/dataforge/context/Context;
+	public abstract fun getData ()Lhep/dataforge/data/DataTreeBuilder;
+	public abstract fun getParentContext ()Lhep/dataforge/context/Context;
+	public abstract fun getTargets ()Ljava/util/Map;
+	public abstract fun getTasks ()Ljava/util/Set;
+	public abstract fun setContext (Lhep/dataforge/context/Context;)V
+	public abstract fun setData (Lhep/dataforge/data/DataTreeBuilder;)V
+	public abstract fun setTargets (Ljava/util/Map;)V
+	public abstract fun setTasks (Ljava/util/Set;)V
+}
+
+public final class hep/dataforge/workspace/WorkspaceBuilderKt {
+	public static final fun context (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public static synthetic fun context$default (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public static final fun rawData (Lhep/dataforge/workspace/WorkspaceBuilder;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataNode;
+	public static synthetic fun rawData$default (Lhep/dataforge/workspace/WorkspaceBuilder;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/data/DataNode;
+	public static final fun rawTask (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/Task;
+	public static final fun target (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public static final fun target (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public static final fun task (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/Task;
+}
+
+public final class hep/dataforge/workspace/WorkspaceKt {
+	public static final fun run (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/Task;Ljava/lang/String;)Lhep/dataforge/data/DataNode;
+	public static final fun run (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/Task;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataNode;
+	public static final fun run (Lhep/dataforge/workspace/Workspace;Ljava/lang/String;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public static final fun run (Lhep/dataforge/workspace/Workspace;Ljava/lang/String;Ljava/lang/String;)Lhep/dataforge/data/DataNode;
+	public static final fun run (Lhep/dataforge/workspace/Workspace;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataNode;
+	public static synthetic fun run$default (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/Task;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/data/DataNode;
+	public static synthetic fun run$default (Lhep/dataforge/workspace/Workspace;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/data/DataNode;
+}
+
+public abstract class hep/dataforge/workspace/WorkspacePlugin : hep/dataforge/context/AbstractPlugin {
+	public fun <init> ()V
+	public fun content (Ljava/lang/String;)Ljava/util/Map;
+	public final fun getTasks ()Ljava/util/Collection;
+	public final fun task (Lhep/dataforge/workspace/Task;)V
+	public final fun task (Ljava/lang/String;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/GenericTask;
+}
+
+public final class hep/dataforge/workspace/WorkspaceTaskDependency : hep/dataforge/workspace/TaskDependency {
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)V
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun resolveTask (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/workspace/Task;
+}
+
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 58592961..1dac01d4 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -10,8 +10,8 @@ pluginManagement {
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
 
-    val toolsVersion = "0.6.1-dev-1.4.20-M1"
-    val kotlinVersion = "1.4.20-M1"
+    val toolsVersion = "0.6.4-dev-1.4.20-M2"
+    val kotlinVersion = "1.4.20-M2"
 
     plugins {
         id("ru.mipt.npm.project") version toolsVersion

From d5992c721db14cb7ab92c92800ec678fb380abd6 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Tue, 10 Nov 2020 19:08:53 +0300
Subject: [PATCH 31/40] Refactor Scheme and MutableItemProvider.kt

---
 build.gradle.kts                              |   2 +-
 dataforge-context/api/dataforge-context.api   |  29 ++++
 .../dataforge/properties/ConfigProperty.kt    |  33 +++++
 .../hep/dataforge/properties/Property.kt      |  48 +++++++
 .../hep/dataforge/properties/bindings.kt      |  32 +++++
 dataforge-data/api/dataforge-data.api         |   1 -
 .../kotlin/hep/dataforge/data/DataFilter.kt   |   2 -
 dataforge-meta/api/dataforge-meta.api         | 136 +++++++++---------
 dataforge-meta/build.gradle.kts               |  12 +-
 .../kotlin/hep/dataforge/meta/Config.kt       |   8 +-
 .../kotlin/hep/dataforge/meta/Configurable.kt |  82 +----------
 .../kotlin/hep/dataforge/meta/Meta.kt         |  12 +-
 .../kotlin/hep/dataforge/meta/MetaBuilder.kt  |   4 +-
 .../hep/dataforge/meta/MetaSerializer.kt      |   3 -
 .../hep/dataforge/meta/MetaWithDefault.kt     |  18 +++
 .../hep/dataforge/meta/MutableItemProvider.kt |  88 ++++++++++++
 .../kotlin/hep/dataforge/meta/MutableMeta.kt  |  82 +----------
 .../kotlin/hep/dataforge/meta/Scheme.kt       | 105 ++++++++------
 .../hep/dataforge/meta/Specification.kt       |  64 +++++++--
 .../kotlin/hep/dataforge/names/Name.kt        |  55 +------
 .../kotlin/hep/dataforge/names/NameToken.kt   |  60 ++++++++
 .../kotlin/hep/dataforge/values/Value.kt      |   1 +
 .../hep/dataforge/values/ValueSerializer.kt   |   4 -
 .../hep/dataforge/meta/MetaDelegateTest.kt    |   3 +-
 .../hep/dataforge/meta/SpecificationTest.kt   |   6 +-
 .../hep/dataforge/tables/MutableTable.kt      |   1 +
 .../hep/dataforge/tables/numericColumns.kt    |   1 +
 .../hep/dataforge/workspace/Dependency.kt     |   2 +-
 28 files changed, 519 insertions(+), 375 deletions(-)
 create mode 100644 dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt
 create mode 100644 dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/Property.kt
 create mode 100644 dataforge-context/src/jsMain/kotlin/hep/dataforge/properties/bindings.kt
 create mode 100644 dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaWithDefault.kt
 create mode 100644 dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt
 create mode 100644 dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/NameToken.kt

diff --git a/build.gradle.kts b/build.gradle.kts
index 0c2a30ab..67b8fec3 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,7 +2,7 @@ plugins {
     id("ru.mipt.npm.project")
 }
 
-val dataforgeVersion by extra("0.2.0-dev-4")
+val dataforgeVersion by extra("0.2.0-dev-6")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/dataforge-context/api/dataforge-context.api b/dataforge-context/api/dataforge-context.api
index 5443d3b3..51349c64 100644
--- a/dataforge-context/api/dataforge-context.api
+++ b/dataforge-context/api/dataforge-context.api
@@ -229,6 +229,35 @@ public abstract interface annotation class hep/dataforge/descriptors/ValueDef :
 	public abstract fun type ()[Lhep/dataforge/values/ValueType;
 }
 
+public final class hep/dataforge/properties/ConfigProperty : hep/dataforge/properties/Property {
+	public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/names/Name;Lhep/dataforge/meta/transformations/MetaConverter;)V
+	public final fun getConfig ()Lhep/dataforge/meta/Config;
+	public final fun getConverter ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public fun getValue ()Ljava/lang/Object;
+	public fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
+	public fun removeChangeListener (Ljava/lang/Object;)V
+	public fun setValue (Ljava/lang/Object;)V
+}
+
+public abstract interface class hep/dataforge/properties/Property {
+	public abstract fun getValue ()Ljava/lang/Object;
+	public abstract fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
+	public abstract fun removeChangeListener (Ljava/lang/Object;)V
+	public abstract fun setValue (Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/properties/Property$DefaultImpls {
+	public static synthetic fun onChange$default (Lhep/dataforge/properties/Property;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public static synthetic fun removeChangeListener$default (Lhep/dataforge/properties/Property;Ljava/lang/Object;ILjava/lang/Object;)V
+}
+
+public final class hep/dataforge/properties/PropertyKt {
+	public static final fun bind (Lhep/dataforge/properties/Property;Lhep/dataforge/properties/Property;)V
+	public static final fun mirror (Lhep/dataforge/properties/Property;Lhep/dataforge/properties/Property;Lkotlinx/coroutines/CoroutineScope;)V
+	public static final fun toFlow (Lhep/dataforge/properties/Property;)Lkotlinx/coroutines/flow/StateFlow;
+}
+
 public final class hep/dataforge/provider/DfTypeKt {
 	public static final fun getDfType (Lkotlin/reflect/KClass;)Ljava/lang/String;
 }
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt
new file mode 100644
index 00000000..329662b5
--- /dev/null
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt
@@ -0,0 +1,33 @@
+package hep.dataforge.properties
+
+import hep.dataforge.meta.Config
+import hep.dataforge.meta.DFExperimental
+import hep.dataforge.meta.get
+import hep.dataforge.meta.transformations.MetaConverter
+import hep.dataforge.meta.transformations.nullableItemToObject
+import hep.dataforge.meta.transformations.nullableObjectToMetaItem
+import hep.dataforge.names.Name
+
+@DFExperimental
+public class ConfigProperty<T : Any>(
+    public val config: Config,
+    public val name: Name,
+    public val converter: MetaConverter<T>,
+) : Property<T?> {
+
+    override var value: T?
+        get() = converter.nullableItemToObject(config[name])
+        set(value) {
+            config.setItem(name,converter.nullableObjectToMetaItem(value))
+        }
+
+    override fun onChange(owner: Any?, callback: (T?) -> Unit) {
+        config.onChange(owner) { name, oldItem, newItem ->
+            if (name == this.name && oldItem != newItem) callback(converter.nullableItemToObject(newItem))
+        }
+    }
+
+    override fun removeChangeListener(owner: Any?) {
+        config.removeListener(owner)
+    }
+}
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/Property.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/Property.kt
new file mode 100644
index 00000000..987cfe4c
--- /dev/null
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/Property.kt
@@ -0,0 +1,48 @@
+package hep.dataforge.properties
+
+import hep.dataforge.meta.DFExperimental
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+@DFExperimental
+public interface Property<T> {
+    public var value: T
+
+    public fun onChange(owner: Any? = null, callback: (T) -> Unit)
+    public fun removeChangeListener(owner: Any? = null)
+}
+
+@DFExperimental
+@OptIn(ExperimentalCoroutinesApi::class)
+public fun <T> Property<T>.toFlow(): StateFlow<T> = MutableStateFlow(value).also { stateFlow ->
+    onChange {
+        stateFlow.value = it
+    }
+}
+
+/**
+ * Reflect all changes in the [source] property onto this property
+ *
+ * @return a mirroring job
+ */
+@DFExperimental
+public fun <T> Property<T>.mirror(source: Property<T>, scope: CoroutineScope) {
+    source.onChange(this) {
+        this.value = it
+    }
+}
+
+/**
+ * Bi-directional connection between properties
+ */
+@DFExperimental
+public fun <T> Property<T>.bind(other: Property<T>) {
+    onChange(other) {
+        other.value = it
+    }
+    other.onChange {
+        this.value = it
+    }
+}
\ No newline at end of file
diff --git a/dataforge-context/src/jsMain/kotlin/hep/dataforge/properties/bindings.kt b/dataforge-context/src/jsMain/kotlin/hep/dataforge/properties/bindings.kt
new file mode 100644
index 00000000..05818cae
--- /dev/null
+++ b/dataforge-context/src/jsMain/kotlin/hep/dataforge/properties/bindings.kt
@@ -0,0 +1,32 @@
+package hep.dataforge.properties
+
+import hep.dataforge.meta.DFExperimental
+import org.w3c.dom.HTMLInputElement
+
+@DFExperimental
+fun HTMLInputElement.bindValue(property: Property<String>) {
+    if (this.onchange != null) error("Input element already bound")
+    this.onchange = {
+        property.value = this.value
+        Unit
+    }
+    property.onChange(this) {
+        if (value != it) {
+            value = it
+        }
+    }
+}
+
+@DFExperimental
+fun HTMLInputElement.bindChecked(property: Property<Boolean>) {
+    if (this.onchange != null) error("Input element already bound")
+    this.onchange = {
+        property.value = this.checked
+        Unit
+    }
+    property.onChange(this) {
+        if (checked != it) {
+            checked = it
+        }
+    }
+}
\ No newline at end of file
diff --git a/dataforge-data/api/dataforge-data.api b/dataforge-data/api/dataforge-data.api
index 60392496..06e99242 100644
--- a/dataforge-data/api/dataforge-data.api
+++ b/dataforge-data/api/dataforge-data.api
@@ -93,7 +93,6 @@ public final class hep/dataforge/data/DataFilter : hep/dataforge/meta/Scheme {
 	public final fun getFrom ()Ljava/lang/String;
 	public final fun getPattern ()Ljava/lang/String;
 	public final fun getTo ()Ljava/lang/String;
-	public final fun isEmpty ()Z
 	public final fun setFrom (Ljava/lang/String;)V
 	public final fun setPattern (Ljava/lang/String;)V
 	public final fun setTo (Ljava/lang/String;)V
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
index 51e58ac6..8369080e 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
@@ -20,8 +20,6 @@ public class DataFilter : Scheme() {
 //    val prefix by string()
 //    val suffix by string()
 
-    public fun isEmpty(): Boolean = config.isEmpty()
-
     public companion object : SchemeSpec<DataFilter>(::DataFilter)
 }
 
diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api
index 5fed772c..743f482a 100644
--- a/dataforge-meta/api/dataforge-meta.api
+++ b/dataforge-meta/api/dataforge-meta.api
@@ -6,8 +6,8 @@ public abstract class hep/dataforge/meta/AbstractMetaNode : hep/dataforge/meta/M
 
 public abstract class hep/dataforge/meta/AbstractMutableMeta : hep/dataforge/meta/AbstractMetaNode, hep/dataforge/meta/MutableMeta {
 	public fun <init> ()V
+	protected final fun getChildren ()Ljava/util/Map;
 	public fun getItems ()Ljava/util/Map;
-	protected final fun get_items ()Ljava/util/Map;
 	protected fun replaceItem (Lhep/dataforge/names/NameToken;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MetaItem;)V
 	public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
 	protected final fun wrapItem (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/meta/MetaItem;
@@ -38,21 +38,15 @@ public final class hep/dataforge/meta/ConfigKt {
 	public static final fun get (Lhep/dataforge/meta/Config;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
 }
 
-public abstract interface class hep/dataforge/meta/Configurable : hep/dataforge/meta/MutableItemProvider, hep/dataforge/meta/descriptors/Described {
+public abstract interface class hep/dataforge/meta/Configurable : hep/dataforge/meta/MutableItemProvider {
 	public abstract fun getConfig ()Lhep/dataforge/meta/Config;
-	public abstract fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
-	public abstract fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
 	public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
 	public abstract fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
-	public abstract fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
 }
 
 public final class hep/dataforge/meta/Configurable$DefaultImpls {
-	public static fun getDefaultItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
-	public static fun getDescriptor (Lhep/dataforge/meta/Configurable;)Lhep/dataforge/meta/descriptors/NodeDescriptor;
 	public static fun getItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
 	public static fun setItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
-	public static fun validateItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
 }
 
 public final class hep/dataforge/meta/ConfigurableKt {
@@ -60,18 +54,6 @@ public final class hep/dataforge/meta/ConfigurableKt {
 	public static synthetic fun config$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
 	public static final fun configure (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Configurable;
 	public static final fun configure (Lhep/dataforge/meta/Configurable;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
-	public static final fun getItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
-	public static final fun node (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
-	public static synthetic fun node$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
-	public static final fun setItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
-	public static final fun setItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
-	public static final fun setItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
-	public static final fun setItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
-	public static final fun setItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;Lhep/dataforge/values/Value;)V
-	public static final fun spec (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
-	public static final fun spec (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
-	public static synthetic fun spec$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
-	public static synthetic fun spec$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
 }
 
 public abstract interface annotation class hep/dataforge/meta/DFBuilder : java/lang/annotation/Annotation {
@@ -196,9 +178,12 @@ public abstract interface class hep/dataforge/meta/Meta : hep/dataforge/meta/Ite
 	public static final field Companion Lhep/dataforge/meta/Meta$Companion;
 	public static final field TYPE Ljava/lang/String;
 	public static final field VALUE_KEY Ljava/lang/String;
+	public abstract fun equals (Ljava/lang/Object;)Z
 	public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
 	public abstract fun getItems ()Ljava/util/Map;
+	public abstract fun hashCode ()I
 	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun toString ()Ljava/lang/String;
 }
 
 public final class hep/dataforge/meta/Meta$Companion {
@@ -358,14 +343,6 @@ public abstract interface class hep/dataforge/meta/MetaRepr {
 	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
 }
 
-public class hep/dataforge/meta/MetaScheme : hep/dataforge/meta/Scheme {
-	public fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;Lhep/dataforge/meta/Config;)V
-	public synthetic fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;Lhep/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-	public fun getDefaultLayer ()Lhep/dataforge/meta/Meta;
-	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
-	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
-}
-
 public final class hep/dataforge/meta/MetaSerializer : kotlinx/serialization/KSerializer {
 	public static final field INSTANCE Lhep/dataforge/meta/MetaSerializer;
 	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/Meta;
@@ -375,6 +352,18 @@ public final class hep/dataforge/meta/MetaSerializer : kotlinx/serialization/KSe
 	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
 }
 
+public final class hep/dataforge/meta/MetaWithDefault : hep/dataforge/meta/MetaBase {
+	public fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)V
+	public final fun getDefault ()Lhep/dataforge/meta/ItemProvider;
+	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public fun getItems ()Ljava/util/Map;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/meta/MetaWithDefaultKt {
+	public static final fun withDefault (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MetaWithDefault;
+}
+
 public final class hep/dataforge/meta/MutableItemDelegateKt {
 	public static final fun boolean (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
 	public static final fun boolean (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
@@ -437,6 +426,29 @@ public abstract interface class hep/dataforge/meta/MutableItemProvider : hep/dat
 	public abstract fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
 }
 
+public final class hep/dataforge/meta/MutableItemProviderKt {
+	public static final fun getItem (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
+	public static final fun node (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun node$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun remove (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)V
+	public static final fun remove (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/NameToken;Ljava/lang/Object;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/Iterable;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/Object;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V
+	public static final fun setIndexed (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
+	public static synthetic fun setIndexed$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+	public static final fun setIndexedItems (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
+	public static synthetic fun setIndexedItems$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+	public static final fun setItem (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
+	public static final fun setNode (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public static final fun setNode (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
+	public static final fun setValue (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
+	public static final fun setValue (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/values/Value;)V
+}
+
 public abstract interface class hep/dataforge/meta/MutableMeta : hep/dataforge/meta/MetaNode, hep/dataforge/meta/MutableItemProvider {
 	public abstract fun getItems ()Ljava/util/Map;
 }
@@ -450,24 +462,6 @@ public final class hep/dataforge/meta/MutableMetaKt {
 	public static final fun append (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
 	public static final fun append (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Object;)V
 	public static final fun edit (Lhep/dataforge/meta/AbstractMutableMeta;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
-	public static final fun remove (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;)V
-	public static final fun remove (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;)V
-	public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
-	public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;)V
-	public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
-	public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/NameToken;Ljava/lang/Object;)V
-	public static final fun set (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Iterable;)V
-	public static final fun set (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Object;)V
-	public static final fun set (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V
-	public static final fun setIndexed (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
-	public static synthetic fun setIndexed$default (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
-	public static final fun setIndexedItems (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
-	public static synthetic fun setIndexedItems$default (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
-	public static final fun setItem (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
-	public static final fun setNode (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
-	public static final fun setNode (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
-	public static final fun setValue (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
-	public static final fun setValue (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Lhep/dataforge/values/Value;)V
 	public static final fun update (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/meta/Meta;)V
 }
 
@@ -483,22 +477,23 @@ public final class hep/dataforge/meta/ObservableMeta$DefaultImpls {
 
 public class hep/dataforge/meta/Scheme : hep/dataforge/meta/Configurable, hep/dataforge/meta/MetaRepr, hep/dataforge/meta/descriptors/Described {
 	public fun <init> ()V
-	public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)V
+	public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
 	public fun getConfig ()Lhep/dataforge/meta/Config;
-	public fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public final fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
 	public fun getDefaultLayer ()Lhep/dataforge/meta/Meta;
-	public final fun getDefaultProvider ()Lhep/dataforge/meta/ItemProvider;
 	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
 	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
 	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public final fun isEmpty ()Z
 	public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
 	public fun toMeta ()Lhep/dataforge/meta/Laminate;
 	public synthetic fun toMeta ()Lhep/dataforge/meta/Meta;
-	public fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+	public final fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
 }
 
 public final class hep/dataforge/meta/SchemeKt {
-	public static final fun asScheme (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaScheme;
+	public static final fun asScheme (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Scheme;
 	public static final fun invoke (Lhep/dataforge/meta/Scheme;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
 	public static final fun toScheme (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
 	public static synthetic fun toScheme$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/Configurable;
@@ -507,12 +502,8 @@ public final class hep/dataforge/meta/SchemeKt {
 public class hep/dataforge/meta/SchemeSpec : hep/dataforge/meta/Specification {
 	public fun <init> (Lkotlin/jvm/functions/Function0;)V
 	public fun <init> (Lkotlin/jvm/functions/Function2;)V
-	public synthetic fun empty ()Lhep/dataforge/meta/Configurable;
-	public fun empty ()Lhep/dataforge/meta/Scheme;
-	public synthetic fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
-	public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
-	public synthetic fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Configurable;
-	public fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
+	public synthetic fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+	public fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
 }
 
 public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractMetaNode {
@@ -520,25 +511,27 @@ public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractMe
 }
 
 public abstract interface class hep/dataforge/meta/Specification {
-	public abstract fun empty ()Lhep/dataforge/meta/Configurable;
-	public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
-	public abstract fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Configurable;
+	public abstract fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
 }
 
 public final class hep/dataforge/meta/Specification$DefaultImpls {
-	public static fun empty (Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/Configurable;
-	public static fun invoke (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
-	public static synthetic fun wrap$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/Configurable;
+	public static synthetic fun wrap$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
 }
 
 public final class hep/dataforge/meta/SpecificationKt {
-	public static final fun configSpec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/Configurable;
-	public static final fun configure (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+	public static final fun configSpec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
+	public static final fun configure (Lhep/dataforge/meta/MetaRepr;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaRepr;
 	public static final fun createStyle (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Meta;
-	public static final fun spec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/Configurable;
+	public static final fun empty (Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
+	public static final fun invoke (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+	public static final fun spec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
+	public static final fun spec (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Scheme;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun spec (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun spec$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Scheme;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun spec$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
 	public static final fun update (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
-	public static final fun update (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
-	public static final fun wrap (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Configurable;
+	public static final fun update (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+	public static final fun wrap (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MutableItemProvider;
 }
 
 public abstract interface class hep/dataforge/meta/descriptors/Described {
@@ -775,7 +768,6 @@ public final class hep/dataforge/names/NameKt {
 	public static final fun get (Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
 	public static synthetic fun get$default (Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/Object;
 	public static final fun getLength (Lhep/dataforge/names/Name;)I
-	public static final fun hasIndex (Lhep/dataforge/names/NameToken;)Z
 	public static final fun isEmpty (Lhep/dataforge/names/Name;)Z
 	public static final fun lastOrNull (Lhep/dataforge/names/Name;)Lhep/dataforge/names/NameToken;
 	public static final fun plus (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
@@ -787,7 +779,6 @@ public final class hep/dataforge/names/NameKt {
 	public static final fun startsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/NameToken;)Z
 	public static final fun toName (Ljava/lang/String;)Lhep/dataforge/names/Name;
 	public static final fun withIndex (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/names/Name;
-	public static final fun withIndex (Lhep/dataforge/names/NameToken;Ljava/lang/String;)Lhep/dataforge/names/NameToken;
 }
 
 public final class hep/dataforge/names/NameToken {
@@ -814,6 +805,11 @@ public final class hep/dataforge/names/NameToken$Companion : kotlinx/serializati
 	public final fun serializer ()Lkotlinx/serialization/KSerializer;
 }
 
+public final class hep/dataforge/names/NameTokenKt {
+	public static final fun hasIndex (Lhep/dataforge/names/NameToken;)Z
+	public static final fun withIndex (Lhep/dataforge/names/NameToken;Ljava/lang/String;)Lhep/dataforge/names/NameToken;
+}
+
 public final class hep/dataforge/values/DoubleArrayValue : hep/dataforge/values/Value {
 	public fun <init> ([D)V
 	public fun equals (Ljava/lang/Object;)Z
diff --git a/dataforge-meta/build.gradle.kts b/dataforge-meta/build.gradle.kts
index 2d4aac0c..980924a7 100644
--- a/dataforge-meta/build.gradle.kts
+++ b/dataforge-meta/build.gradle.kts
@@ -1,16 +1,12 @@
-import ru.mipt.npm.gradle.KScienceVersions
-
 plugins {
     id("ru.mipt.npm.mpp")
     id("ru.mipt.npm.native")
 }
 
 kscience {
-    useSerialization()
+    useSerialization{
+        json()
+    }
 }
 
-description = "Meta definition and basic operations on meta"
-
-dependencies{
-    commonMainApi("org.jetbrains.kotlinx:kotlinx-serialization-json:${KScienceVersions.serializationVersion}")
-}
\ No newline at end of file
+description = "Meta definition and basic operations on meta"
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
index d1691e4e..2674d0a8 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
@@ -4,10 +4,8 @@ import hep.dataforge.names.Name
 import hep.dataforge.names.NameToken
 import hep.dataforge.names.asName
 import hep.dataforge.names.plus
-import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.Serializable
-import kotlinx.serialization.Serializer
 import kotlinx.serialization.descriptors.SerialDescriptor
 import kotlinx.serialization.encoding.Decoder
 import kotlinx.serialization.encoding.Encoder
@@ -53,12 +51,12 @@ public class Config() : AbstractMutableMeta<Config>(), ObservableMeta {
 
     override fun replaceItem(key: NameToken, oldItem: MetaItem<Config>?, newItem: MetaItem<Config>?) {
         if (newItem == null) {
-            _items.remove(key)
+            children.remove(key)
             if (oldItem != null && oldItem is MetaItem.NodeItem<Config>) {
                 oldItem.node.removeListener(this)
             }
         } else {
-            _items[key] = newItem
+            children[key] = newItem
             if (newItem is MetaItem.NodeItem) {
                 newItem.node.onChange(this) { name, oldChild, newChild ->
                     itemChanged(key + name, oldChild, newChild)
@@ -75,8 +73,6 @@ public class Config() : AbstractMutableMeta<Config>(), ObservableMeta {
 
     override fun empty(): Config = Config()
 
-    @OptIn(ExperimentalSerializationApi::class)
-    @Serializer(Config::class)
     public companion object ConfigSerializer : KSerializer<Config> {
 
         public fun empty(): Config = Config()
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
index 9fd6cdb3..2308bef2 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
@@ -1,67 +1,30 @@
 package hep.dataforge.meta
 
-import hep.dataforge.meta.descriptors.*
 import hep.dataforge.names.Name
-import hep.dataforge.names.asName
-import hep.dataforge.names.toName
-import hep.dataforge.values.Value
 import kotlin.properties.ReadWriteProperty
-import kotlin.reflect.KProperty
 
 /**
- * A container that holds a [Config] and a default item provider.
- * Default item provider could be use for example to reference parent configuration.
- * It is not possible to know if some property is declared by provider just by looking on [Configurable],
- * this information should be provided externally.
+ * A container that holds a [Config].
  */
-public interface Configurable : Described, MutableItemProvider {
+public interface Configurable : MutableItemProvider {
     /**
      * Backing config
      */
     public val config: Config
 
-    /**
-     * Default meta item provider
-     */
-    public fun getDefaultItem(name: Name): MetaItem<*>? = null
-
-    /**
-     * Check if property with given [name] could be assigned to [item]
-     */
-    public fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
-        val descriptor = descriptor?.get(name)
-        return descriptor?.validateItem(item) ?: true
-    }
-
-    override val descriptor: NodeDescriptor? get() = null
-
     /**
      * Get a property with default
      */
-    override fun getItem(name: Name): MetaItem<*>? =
-        config[name] ?: getDefaultItem(name) ?: descriptor?.get(name)?.defaultItem()
+    override fun getItem(name: Name): MetaItem<*>? = config[name]
 
     /**
      * Set a configurable property
      */
     override fun setItem(name: Name, item: MetaItem<*>?) {
-        if (validateItem(name, item)) {
-            config.setItem(name, item)
-        } else {
-            error("Validation failed for property $name with value $item")
-        }
+        config.setItem(name, item)
     }
 }
 
-public fun Configurable.getItem(key: String): MetaItem<*>? = getItem(key.toName())
-
-public fun Configurable.setItem(name: Name, value: Value?): Unit = setItem(name, value?.let { MetaItem.ValueItem(value) })
-public fun Configurable.setItem(name: Name, meta: Meta?): Unit = setItem(name, meta?.let { MetaItem.NodeItem(meta) })
-
-public fun Configurable.setItem(key: String, item: MetaItem<*>?): Unit = setItem(key.toName(), item)
-
-public fun Configurable.setItem(key: String, value: Value?): Unit = setItem(key, value?.let { MetaItem.ValueItem(value) })
-public fun Configurable.setItem(key: String, meta: Meta?): Unit = setItem(key, meta?.let { MetaItem.NodeItem(meta) })
 
 public fun <T : Configurable> T.configure(meta: Meta): T = this.apply { config.update(meta) }
 
@@ -70,39 +33,4 @@ public inline fun <T : Configurable> T.configure(action: Config.() -> Unit): T =
 
 /* Node delegates */
 
-public fun Configurable.config(key: Name? = null): ReadWriteProperty<Any?, Config?> =
-    config.node(key)
-
-public fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
-    reader = { it.node },
-    writer = { it?.let { MetaItem.NodeItem(it) } }
-)
-
-public fun <T : Configurable> Configurable.spec(
-    spec: Specification<T>, key: Name? = null
-): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
-        val name = key ?: property.name.asName()
-        return config[name].node?.let { spec.wrap(it) }
-    }
-
-    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
-        val name = key ?: property.name.asName()
-        config[name] = value?.config
-    }
-}
-
-public fun <T : Configurable> Configurable.spec(
-    spec: Specification<T>, default: T, key: Name? = null
-): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
-        val name = key ?: property.name.asName()
-        return config[name].node?.let { spec.wrap(it) } ?: default
-    }
-
-    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
-        val name = key ?: property.name.asName()
-        config[name] = value.config
-    }
-}
-
+public fun Configurable.config(key: Name? = null): ReadWriteProperty<Any?, Config?> = config.node(key)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
index 5c992c6b..c8ed6755 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
@@ -66,6 +66,7 @@ public fun <M : Meta> M.asMetaItem(): NodeItem<M> = NodeItem(this)
  * The object that could be represented as [Meta]. Meta provided by [toMeta] method should fully represent object state.
  * Meaning that two states with the same meta are equal.
  */
+@Serializable(MetaSerializer::class)
 public interface MetaRepr {
     public fun toMeta(): Meta
 }
@@ -104,12 +105,11 @@ public interface Meta : MetaRepr, ItemProvider {
 
     override fun toMeta(): Meta = seal()
 
-    //TODO to be restored on 1.4.30 after https://youtrack.jetbrains.com/issue/KT-41765 si fixed
-//    override fun equals(other: Any?): Boolean
-//
-//    override fun hashCode(): Int
-//
-//    override fun toString(): String
+    override fun equals(other: Any?): Boolean
+
+    override fun hashCode(): Int
+
+    override fun toString(): String
 
     public companion object {
         public const val TYPE: String = "meta"
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt
index b6e933f6..cd041275 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt
@@ -68,7 +68,7 @@ public class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
 
     @JvmName("putMetas")
     public infix fun String.put(value: Iterable<Meta>) {
-        this@MetaBuilder[this] = value.toList()
+        set(this,value.toList())
     }
 
     public infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) {
@@ -110,7 +110,7 @@ public class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
 
     @JvmName("putMetas")
     public infix fun Name.put(value: Iterable<Meta>) {
-        this@MetaBuilder[this] = value.toList()
+        set(this, value.toList())
     }
 
     public infix fun Name.put(metaBuilder: MetaBuilder.() -> Unit) {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
index 7184ae3a..b20adba8 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
@@ -5,7 +5,6 @@ import hep.dataforge.values.ValueSerializer
 import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.InternalSerializationApi
 import kotlinx.serialization.KSerializer
-import kotlinx.serialization.Serializer
 import kotlinx.serialization.builtins.MapSerializer
 import kotlinx.serialization.descriptors.*
 import kotlinx.serialization.encoding.*
@@ -52,8 +51,6 @@ public object MetaItemSerializer : KSerializer<MetaItem<*>> {
 /**
  * Serialized for meta
  */
-@OptIn(ExperimentalSerializationApi::class)
-@Serializer(Meta::class)
 public object MetaSerializer : KSerializer<Meta> {
 
     private val mapSerializer: KSerializer<Map<NameToken, MetaItem<Meta>>> = MapSerializer(
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaWithDefault.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaWithDefault.kt
new file mode 100644
index 00000000..2a225121
--- /dev/null
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaWithDefault.kt
@@ -0,0 +1,18 @@
+package hep.dataforge.meta
+
+import hep.dataforge.names.Name
+import hep.dataforge.names.NameToken
+
+/**
+ * Meta object with default provider for items not present in the initial meta.
+ */
+public class MetaWithDefault(public val meta: Meta, public val default: ItemProvider) : MetaBase() {
+    override val items: Map<NameToken, MetaItem<*>>
+        get() = meta.items
+
+    override fun getItem(name: Name): MetaItem<*>? {
+        return meta[name] ?: default.getItem(name)
+    }
+}
+
+public fun Meta.withDefault(default: ItemProvider): MetaWithDefault = MetaWithDefault(this, default)
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt
new file mode 100644
index 00000000..6a43af6e
--- /dev/null
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt
@@ -0,0 +1,88 @@
+package hep.dataforge.meta
+
+import hep.dataforge.names.*
+import hep.dataforge.values.Value
+import kotlin.properties.ReadWriteProperty
+
+public interface MutableItemProvider : ItemProvider {
+    public fun setItem(name: Name, item: MetaItem<*>?)
+}
+
+public fun MutableItemProvider.getItem(key: String): MetaItem<*>? = getItem(key.toName())
+
+public fun MutableItemProvider.setValue(name: Name, value: Value?): Unit =
+    setItem(name, value?.let { MetaItem.ValueItem(value) })
+
+public fun MutableItemProvider.setNode(name: Name, meta: Meta?): Unit =
+    setItem(name, meta?.let { MetaItem.NodeItem(meta) })
+
+public fun MutableItemProvider.setItem(key: String, item: MetaItem<*>?): Unit = setItem(key.toName(), item)
+
+public fun MutableItemProvider.setValue(key: String, value: Value?): Unit =
+    setItem(key, value?.let { MetaItem.ValueItem(value) })
+
+public fun MutableItemProvider.setNode(key: String, meta: Meta?): Unit =
+    setItem(key, meta?.let { MetaItem.NodeItem(meta) })
+
+public fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
+    reader = { it.node },
+    writer = { it?.let { MetaItem.NodeItem(it) } }
+)
+
+@Suppress("NOTHING_TO_INLINE")
+public inline fun MutableItemProvider.remove(name: Name): Unit = setItem(name, null)
+
+@Suppress("NOTHING_TO_INLINE")
+public inline fun MutableItemProvider.remove(name: String): Unit = remove(name.toName())
+
+
+/**
+ * Universal unsafe set method
+ */
+public operator fun MutableItemProvider.set(name: Name, value: Any?) {
+    when (value) {
+        null -> remove(name)
+        is MetaItem<*> -> setItem(name, value)
+        is Meta -> setNode(name, value)
+        is Configurable -> setNode(name, value.config)
+        else -> setValue(name, Value.of(value))
+    }
+}
+
+public operator fun MutableItemProvider.set(name: NameToken, value: Any?): Unit =
+    set(name.asName(), value)
+
+public operator fun MutableItemProvider.set(key: String, value: Any?): Unit =
+    set(key.toName(), value)
+
+public operator fun MutableItemProvider.set(key: String, index: String, value: Any?): Unit =
+    set(key.toName().withIndex(index), value)
+
+
+
+/* Same name siblings generation */
+
+public fun MutableItemProvider.setIndexedItems(
+    name: Name,
+    items: Iterable<MetaItem<*>>,
+    indexFactory: (MetaItem<*>, index: Int) -> String = { _, index -> index.toString() }
+) {
+    val tokens = name.tokens.toMutableList()
+    val last = tokens.last()
+    items.forEachIndexed { index, meta ->
+        val indexedToken = NameToken(last.body, last.index + indexFactory(meta, index))
+        tokens[tokens.lastIndex] = indexedToken
+        setItem(Name(tokens), meta)
+    }
+}
+
+public fun MutableItemProvider.setIndexed(
+    name: Name,
+    metas: Iterable<Meta>,
+    indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }
+) {
+    setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }) { item, index -> indexFactory(item.node!!, index) }
+}
+
+public operator fun MutableItemProvider.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
+public operator fun MutableItemProvider.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
index 25cf003f..7903ba87 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
@@ -1,11 +1,6 @@
 package hep.dataforge.meta
 
 import hep.dataforge.names.*
-import hep.dataforge.values.Value
-
-public interface MutableItemProvider : ItemProvider {
-    public fun setItem(name: Name, item: MetaItem<*>?)
-}
 
 public interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider {
     override val items: Map<NameToken, MetaItem<M>>
@@ -19,18 +14,18 @@ public interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemP
  * Changes in Meta are not thread safe.
  */
 public abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
-    protected val _items: MutableMap<NameToken, MetaItem<M>> = LinkedHashMap()
+    protected val children: MutableMap<NameToken, MetaItem<M>> = LinkedHashMap()
 
     override val items: Map<NameToken, MetaItem<M>>
-        get() = _items
+        get() = children
 
     //protected abstract fun itemChanged(name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?)
 
     protected open fun replaceItem(key: NameToken, oldItem: MetaItem<M>?, newItem: MetaItem<M>?) {
         if (newItem == null) {
-            _items.remove(key)
+            children.remove(key)
         } else {
-            _items[key] = newItem
+            children[key] = newItem
         }
         //itemChanged(key.asName(), oldItem, newItem)
     }
@@ -72,48 +67,6 @@ public abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode
     }
 }
 
-
-@Suppress("NOTHING_TO_INLINE")
-public inline fun MutableMeta<*>.remove(name: Name): Unit = setItem(name, null)
-
-@Suppress("NOTHING_TO_INLINE")
-public inline fun MutableMeta<*>.remove(name: String): Unit = remove(name.toName())
-
-public operator fun MutableMeta<*>.set(name: Name, item: MetaItem<*>?): Unit = setItem(name, item)
-
-public fun MutableMeta<*>.setValue(name: Name, value: Value): Unit = setItem(name, MetaItem.ValueItem(value))
-
-public fun MutableMeta<*>.setValue(name: String, value: Value): Unit = set(name.toName(), value)
-
-public fun MutableMeta<*>.setItem(name: String, item: MetaItem<*>?): Unit = setItem(name.toName(), item)
-
-public fun MutableMeta<*>.setNode(name: Name, node: Meta): Unit =
-    setItem(name, MetaItem.NodeItem(node))
-
-public fun MutableMeta<*>.setNode(name: String, node: Meta): Unit = setNode(name.toName(), node)
-
-/**
- * Universal unsafe set method
- */
-public operator fun MutableMeta<*>.set(name: Name, value: Any?) {
-    when (value) {
-        null -> remove(name)
-        is MetaItem<*> -> setItem(name, value)
-        is Meta -> setNode(name, value)
-        is Configurable -> setNode(name, value.config)
-        else -> setValue(name, Value.of(value))
-    }
-}
-
-public operator fun MutableMeta<*>.set(name: NameToken, value: Any?): Unit =
-    set(name.asName(), value)
-
-public operator fun MutableMeta<*>.set(key: String, value: Any?): Unit =
-    set(key.toName(), value)
-
-public operator fun MutableMeta<*>.set(key: String, index: String, value: Any?): Unit =
-    set(key.toName().withIndex(index), value)
-
 /**
  * Update existing mutable node with another node. The rules are following:
  *  * value replaces anything
@@ -130,33 +83,6 @@ public fun <M : MutableMeta<M>> M.update(meta: Meta) {
     }
 }
 
-/* Same name siblings generation */
-
-public fun MutableMeta<*>.setIndexedItems(
-    name: Name,
-    items: Iterable<MetaItem<*>>,
-    indexFactory: (MetaItem<*>, index: Int) -> String = { _, index -> index.toString() }
-) {
-    val tokens = name.tokens.toMutableList()
-    val last = tokens.last()
-    items.forEachIndexed { index, meta ->
-        val indexedToken = NameToken(last.body, last.index + indexFactory(meta, index))
-        tokens[tokens.lastIndex] = indexedToken
-        setItem(Name(tokens), meta)
-    }
-}
-
-public fun MutableMeta<*>.setIndexed(
-    name: Name,
-    metas: Iterable<Meta>,
-    indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }
-) {
-    setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }) { item, index -> indexFactory(item.node!!, index) }
-}
-
-public operator fun MutableMeta<*>.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
-public operator fun MutableMeta<*>.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)
-
 /**
  * Append the node with a same-name-sibling, automatically generating numerical index
  */
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
index 913f5a3d..a85e464f 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
@@ -1,31 +1,49 @@
 package hep.dataforge.meta
 
-import hep.dataforge.meta.descriptors.Described
-import hep.dataforge.meta.descriptors.NodeDescriptor
-import hep.dataforge.meta.descriptors.defaultItem
-import hep.dataforge.meta.descriptors.get
+import hep.dataforge.meta.descriptors.*
 import hep.dataforge.names.Name
 import hep.dataforge.names.NameToken
 import hep.dataforge.names.asName
 
 /**
  * A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
+ * Default item provider and [NodeDescriptor] are optional
  */
 public open class Scheme(
-    config: Config,
-    defaultProvider: ItemProvider,
+    config: Config = Config(),
+    internal var default: ItemProvider? = null,
+    override val descriptor: NodeDescriptor? = null,
 ) : Configurable, Described, MetaRepr {
 
     override var config: Config = config
         internal set
 
-    public var defaultProvider: ItemProvider = defaultProvider
-        internal set
+    public fun getDefaultItem(name: Name): MetaItem<*>? {
+        return default?.getItem(name) ?: descriptor?.get(name)?.defaultItem()
+    }
 
-    public constructor() : this(Config(), ItemProvider { null })
+    /**
+     * Get a property with default
+     */
+    override fun getItem(name: Name): MetaItem<*>? = config[name] ?: getDefaultItem(name)
 
-    override fun getDefaultItem(name: Name): MetaItem<*>? {
-        return defaultProvider.getItem(name) ?: descriptor?.get(name)?.defaultItem()
+    /**
+     * Check if property with given [name] could be assigned to [item]
+     */
+    public fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
+        val descriptor = descriptor?.get(name)
+        return descriptor?.validateItem(item) ?: true
+    }
+
+    /**
+     * Set a configurable property
+     */
+    override fun setItem(name: Name, item: MetaItem<*>?) {
+        if (validateItem(name, item)) {
+            super.setItem(name, item)
+        } else {
+            error("Validation failed for property $name with value $item")
+        }
     }
 
     /**
@@ -33,22 +51,23 @@ public open class Scheme(
      * values if default value is unavailable.
      * Values from [defaultProvider] completely replace
      */
-    public open val defaultLayer: Meta get() = DefaultLayer()
-
-    override fun toMeta(): Laminate = Laminate(config, defaultLayer)
-
-    private inner class DefaultLayer : MetaBase() {
-        override val items: Map<NameToken, MetaItem<*>> = buildMap {
-            descriptor?.items?.forEach { (key, itemDescriptor) ->
-                val token = NameToken(key)
-                val name = token.asName()
-                val item = defaultProvider.getItem(name) ?: itemDescriptor.defaultItem()
-                if (item != null) {
-                    put(token, item)
+    public open val defaultLayer: Meta
+        get() = object : MetaBase() {
+            override val items: Map<NameToken, MetaItem<*>> = buildMap {
+                descriptor?.items?.forEach { (key, itemDescriptor) ->
+                    val token = NameToken(key)
+                    val name = token.asName()
+                    val item = default?.getItem(name) ?: itemDescriptor.defaultItem()
+                    if (item != null) {
+                        put(token, item)
+                    }
                 }
             }
         }
-    }
+
+    override fun toMeta(): Laminate = Laminate(config, defaultLayer)
+
+    public fun isEmpty(): Boolean = config.isEmpty()
 }
 
 /**
@@ -66,30 +85,32 @@ public open class SchemeSpec<T : Scheme>(
     public constructor(emptyBuilder: () -> T) : this({ config: Config, defaultProvider: ItemProvider ->
         emptyBuilder().apply {
             this.config = config
-            this.defaultProvider = defaultProvider
+            this.default = defaultProvider
         }
     })
 
-    override fun empty(): T = builder(Config(), ItemProvider.EMPTY)
-
-    override fun wrap(config: Config, defaultProvider: ItemProvider): T = builder(config, defaultProvider)
-
-    @Suppress("OVERRIDE_BY_INLINE")
-    final override inline operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
+    /**
+     * If the provided [Meta] is a [Config] use it as a scheme base, otherwise use it as default.
+     */
+    override fun wrap(meta: Meta, defaultProvider: ItemProvider): T = if (meta is Config) {
+        builder(meta, defaultProvider)
+    } else {
+        builder(Config(), meta.withDefault(defaultProvider))
+    }
 }
 
-/**
- * A scheme that uses [Meta] as a default layer
- */
-public open class MetaScheme(
-    private val meta: Meta,
-    override val descriptor: NodeDescriptor? = null,
-    config: Config = Config(),
-) : Scheme(config, meta) {
-    override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
-}
+///**
+// * A scheme that uses [Meta] as a default layer
+// */
+//public open class MetaScheme(
+//    private val meta: Meta,
+//    override val descriptor: NodeDescriptor? = null,
+//    config: Config = Config(),
+//) : Scheme(config, meta) {
+//    override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
+//}
 
-public fun Meta.asScheme(): MetaScheme = MetaScheme(this)
+public fun Meta.asScheme(): Scheme = Scheme(this.asConfig(), null, null)
 
 public fun <T : Configurable> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit = {}): T =
     spec.wrap(this).apply(block)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
index 7988f0c1..03bc36b6 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
@@ -1,32 +1,36 @@
 package hep.dataforge.meta
 
+import hep.dataforge.names.Name
+import hep.dataforge.names.asName
 import kotlin.jvm.JvmName
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
 
 /**
  * Allows to apply custom configuration in a type safe way to simple untyped configuration.
  * By convention [Scheme] companion should inherit this class
  *
  */
-public interface Specification<T : Configurable> {
-    public fun empty(): T = wrap()
-
+public interface Specification<T : MutableItemProvider> {
     /**
      * Wrap generic configuration producing instance of desired type
      */
-    public fun wrap(config: Config = Config(), defaultProvider: ItemProvider = ItemProvider{ null }): T
-
-    public operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
+    public fun wrap(meta: Meta, defaultProvider: ItemProvider = ItemProvider.EMPTY): T
 }
 
+public operator fun <T : MutableItemProvider> Specification<T>.invoke(action: T.() -> Unit): T = empty().apply(action)
+
+public fun <T : MutableItemProvider> Specification<T>.empty(): T = wrap(Config())
+
 /**
  * Update given configuration using given type as a builder
  */
-public fun <T : Configurable> Specification<T>.update(config: Config, action: T.() -> Unit): T = wrap(config).apply(action)
+public fun <T : MutableItemProvider> Specification<T>.update(meta: Meta, action: T.() -> Unit): T = wrap(meta).apply(action)
 
 /**
- * Wrap a configuration using static meta as default
+ * Create a read-only version of
  */
-public fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
+public fun <T : MutableItemProvider> Specification<T>.wrap(source: Meta): T {
     val default = source.seal()
     return wrap(source.asConfig(), default)
 }
@@ -34,26 +38,56 @@ public fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
 /**
  * Apply specified configuration to configurable
  */
-public fun <T : Configurable, C : Configurable, S : Specification<C>> T.configure(spec: S, action: C.() -> Unit): T =
-    apply { spec.update(config, action) }
+public fun <T : MetaRepr, C : MutableItemProvider, S : Specification<C>> T.configure(spec: S, action: C.() -> Unit): T =
+    apply { spec.update(toMeta(), action) }
 
 /**
  * Update configuration using given specification
  */
-public fun <C : Configurable, S : Specification<C>> Configurable.update(spec: S, action: C.() -> Unit): Configurable =
+public fun <C : MutableItemProvider, S : Specification<C>> Configurable.update(spec: S, action: C.() -> Unit): Configurable =
     apply { spec.update(config, action) }
 
 /**
  * Create a style based on given specification
  */
-public fun <C : Configurable, S : Specification<C>> S.createStyle(action: C.() -> Unit): Meta =
+public fun <C : MutableItemProvider, S : Specification<C>> S.createStyle(action: C.() -> Unit): Meta =
     Config().also { update(it, action) }
 
-public fun <T : Configurable> MetaItem<*>.spec(spec: Specification<T>): T? = node?.let {
+public fun <T : MutableItemProvider> MetaItem<*>.spec(spec: Specification<T>): T? = node?.let {
     spec.wrap(
         Config(), it
     )
 }
 
 @JvmName("configSpec")
-public fun <T : Configurable> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
+public fun <T : MutableItemProvider> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
+
+public fun <T : Scheme> MutableItemProvider.spec(
+    spec: Specification<T>, key: Name? = null
+): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
+    override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
+        val name = key ?: property.name.asName()
+        return getItem(name).node?.let { spec.wrap(it) }
+    }
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
+        val name = key ?: property.name.asName()
+        setItem(name, value?.toMeta()?.asMetaItem())
+    }
+}
+
+public fun <T : Scheme> MutableItemProvider.spec(
+    spec: Specification<T>,
+    default: T,
+    key: Name? = null
+): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
+    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
+        val name = key ?: property.name.asName()
+        return getItem(name).node?.let { spec.wrap(it) } ?: default
+    }
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
+        val name = key ?: property.name.asName()
+        setItem(name, value.toMeta().asMetaItem())
+    }
+}
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
index 0791e080..9cce4314 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
@@ -1,9 +1,7 @@
 package hep.dataforge.names
 
-import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.Serializable
-import kotlinx.serialization.Serializer
 import kotlinx.serialization.descriptors.PrimitiveKind
 import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
 import kotlinx.serialization.descriptors.SerialDescriptor
@@ -16,7 +14,7 @@ import kotlinx.serialization.encoding.Encoder
  * The name is a dot separated list of strings like `token1.token2.token3`.
  * Each token could contain additional index in square brackets.
  */
-@Serializable
+@Serializable(Name.Companion::class)
 public class Name(public val tokens: List<NameToken>) {
     //TODO to be transformed into inline class after they are supported with serialization
 
@@ -38,8 +36,6 @@ public class Name(public val tokens: List<NameToken>) {
         }
     }
 
-    @OptIn(ExperimentalSerializationApi::class)
-    @Serializer(Name::class)
     public companion object : KSerializer<Name> {
         public const val NAME_SEPARATOR: String = "."
 
@@ -82,55 +78,6 @@ public fun Name.lastOrNull(): NameToken? = tokens.lastOrNull()
  */
 public fun Name.firstOrNull(): NameToken? = tokens.firstOrNull()
 
-/**
- * A single name token. Body is not allowed to be empty.
- * Following symbols are prohibited in name tokens: `{}.:\`.
- * A name token could have appendix in square brackets called *index*
- */
-@Serializable
-public data class NameToken(val body: String, val index: String? = null) {
-
-    init {
-        if (body.isEmpty()) error("Syntax error: Name token body is empty")
-    }
-
-    private fun String.escape() =
-        replace("\\", "\\\\")
-            .replace(".", "\\.")
-            .replace("[", "\\[")
-            .replace("]", "\\]")
-
-    override fun toString(): String = if (hasIndex()) {
-        "${body.escape()}[$index]"
-    } else {
-        body.escape()
-    }
-
-    @OptIn(ExperimentalSerializationApi::class)
-    @Serializer(NameToken::class)
-    public companion object : KSerializer<NameToken> {
-        override val descriptor: SerialDescriptor =
-            PrimitiveSerialDescriptor("hep.dataforge.names.NameToken", PrimitiveKind.STRING)
-
-        override fun deserialize(decoder: Decoder): NameToken {
-            return decoder.decodeString().toName().firstOrNull()!!
-        }
-
-        override fun serialize(encoder: Encoder, value: NameToken) {
-            encoder.encodeString(value.toString())
-        }
-    }
-}
-
-/**
- * Check if index is defined for this token
- */
-public fun NameToken.hasIndex(): Boolean = index != null
-
-/**
- * Add or replace index part of this token
- */
-public fun NameToken.withIndex(newIndex: String): NameToken = NameToken(body, newIndex)
 
 /**
  * Convert a [String] to name parsing it and extracting name tokens and index syntax.
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/NameToken.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/NameToken.kt
new file mode 100644
index 00000000..d010ac5a
--- /dev/null
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/NameToken.kt
@@ -0,0 +1,60 @@
+package hep.dataforge.names
+
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+
+/**
+ * A single name token. Body is not allowed to be empty.
+ * Following symbols are prohibited in name tokens: `{}.:\`.
+ * A name token could have appendix in square brackets called *index*
+ */
+@Serializable(NameToken.Companion::class)
+public data class NameToken(val body: String, val index: String? = null) {
+
+    init {
+        if (body.isEmpty()) error("Syntax error: Name token body is empty")
+    }
+
+    private fun String.escape() =
+        replace("\\", "\\\\")
+            .replace(".", "\\.")
+            .replace("[", "\\[")
+            .replace("]", "\\]")
+
+    override fun toString(): String = if (hasIndex()) {
+        "${body.escape()}[$index]"
+    } else {
+        body.escape()
+    }
+
+    public companion object : KSerializer<NameToken> {
+        override val descriptor: SerialDescriptor =
+            PrimitiveSerialDescriptor("hep.dataforge.names.NameToken", PrimitiveKind.STRING)
+
+        override fun deserialize(decoder: Decoder): NameToken {
+            return decoder.decodeString().toName().firstOrNull()!!
+        }
+
+        override fun serialize(
+            encoder: Encoder,
+            value: NameToken,
+        ) {
+            encoder.encodeString(value.toString())
+        }
+    }
+}
+
+/**
+ * Check if index is defined for this token
+ */
+public fun NameToken.hasIndex(): Boolean = index != null
+
+/**
+ * Add or replace index part of this token
+ */
+public fun NameToken.withIndex(newIndex: String): NameToken = NameToken(body, newIndex)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
index 9136d525..ca78f0ae 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
@@ -19,6 +19,7 @@ public enum class ValueType {
  *
  * Value can represent a list of value objects.
  */
+@Serializable(ValueSerializer::class)
 public interface Value {
     /**
      * Get raw value of this value
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
index f7693646..08b87c18 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
@@ -1,8 +1,6 @@
 package hep.dataforge.values
 
-import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.KSerializer
-import kotlinx.serialization.Serializer
 import kotlinx.serialization.builtins.ListSerializer
 import kotlinx.serialization.descriptors.SerialDescriptor
 import kotlinx.serialization.descriptors.buildClassSerialDescriptor
@@ -10,8 +8,6 @@ import kotlinx.serialization.descriptors.element
 import kotlinx.serialization.encoding.Decoder
 import kotlinx.serialization.encoding.Encoder
 
-@OptIn(ExperimentalSerializationApi::class)
-@Serializer(Value::class)
 public object ValueSerializer : KSerializer<Value> {
     private val listSerializer by lazy { ListSerializer(ValueSerializer) }
 
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaDelegateTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaDelegateTest.kt
index 925ee36c..6b8442d1 100644
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaDelegateTest.kt
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaDelegateTest.kt
@@ -1,5 +1,6 @@
 package hep.dataforge.meta
 
+import hep.dataforge.values.asValue
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
@@ -29,7 +30,7 @@ class MetaDelegateTest {
     fun delegateTest() {
 
         val testObject = TestScheme.empty()
-        testObject.config["myValue"] = "theString"
+        testObject.setValue("myValue","theString".asValue())
         testObject.enumValue = TestEnum.NO
 
         testObject.inner = InnerSpec { innerValue = "ddd" }
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
index e74c7bb3..bf73ba8c 100644
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
@@ -9,10 +9,8 @@ class SpecificationTest {
         var list by numberList(1, 2, 3)
 
         companion object : Specification<TestStyled> {
-            override fun wrap(
-                config: Config,
-                defaultProvider: ItemProvider
-            ): TestStyled = TestStyled(config, defaultProvider)
+            override fun wrap(meta: Meta, defaultProvider: ItemProvider): TestStyled =
+                TestStyled(meta.asConfig(), defaultProvider)
         }
     }
 
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt
index 7a1e0376..f4070146 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt
@@ -1,6 +1,7 @@
 package hep.dataforge.tables
 
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.invoke
 import hep.dataforge.values.Value
 import kotlin.reflect.KClass
 
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt
index cc386c35..86868a22 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt
@@ -1,6 +1,7 @@
 package hep.dataforge.tables
 
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.invoke
 import kotlin.reflect.KClass
 
 
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt
index 10bf38d6..e58a988b 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt
@@ -29,7 +29,7 @@ public class DataDependency(private val filter: DataFilter, private val placemen
     }
 
     override fun toMeta(): Meta = Meta {
-        "data" put filter.config
+        "data" put filter.toMeta()
         "to" put placement.toString()
     }
 }

From 3ab3f2766c724d0f2191ca158fbcb48ececaee00 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Tue, 10 Nov 2020 20:18:54 +0300
Subject: [PATCH 32/40] Add preemptive initialization for plugins

---
 dataforge-context/api/dataforge-context.api   |  8 ++---
 .../kotlin/hep/dataforge/context/Context.kt   | 30 ++-----------------
 .../hep/dataforge/context/ContextBuilder.kt   | 15 +++++-----
 .../hep/dataforge/context/PluginManager.kt    | 18 +++++------
 .../hep/dataforge/workspace/Workspace.kt      | 20 ++++++-------
 5 files changed, 28 insertions(+), 63 deletions(-)

diff --git a/dataforge-context/api/dataforge-context.api b/dataforge-context/api/dataforge-context.api
index 51349c64..39fa72d8 100644
--- a/dataforge-context/api/dataforge-context.api
+++ b/dataforge-context/api/dataforge-context.api
@@ -39,12 +39,11 @@ public final class hep/dataforge/context/ClassLoaderPluginKt {
 public class hep/dataforge/context/Context : hep/dataforge/context/Named, hep/dataforge/meta/MetaRepr, hep/dataforge/provider/Provider, kotlinx/coroutines/CoroutineScope {
 	public static final field Companion Lhep/dataforge/context/Context$Companion;
 	public static final field PROPERTY_TARGET Ljava/lang/String;
-	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;)V
-	public final fun activate (Ljava/lang/Object;)V
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;Ljava/util/Set;)V
+	public synthetic fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
 	public fun close ()V
 	public fun content (Ljava/lang/String;)Ljava/util/Map;
 	public final fun content (Ljava/lang/String;Z)Ljava/util/Map;
-	public final fun deactivate (Ljava/lang/Object;)V
 	public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
 	public fun getDefaultChainTarget ()Ljava/lang/String;
 	public fun getDefaultTarget ()Ljava/lang/String;
@@ -52,7 +51,6 @@ public class hep/dataforge/context/Context : hep/dataforge/context/Named, hep/da
 	public final fun getName ()Lhep/dataforge/names/Name;
 	public final fun getParent ()Lhep/dataforge/context/Context;
 	public final fun getPlugins ()Lhep/dataforge/context/PluginManager;
-	public final fun isActive ()Z
 	public fun toMeta ()Lhep/dataforge/meta/Meta;
 }
 
@@ -152,7 +150,7 @@ public final class hep/dataforge/context/PluginFactory$Companion {
 }
 
 public final class hep/dataforge/context/PluginManager : hep/dataforge/context/ContextAware, java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
-	public fun <init> (Lhep/dataforge/context/Context;)V
+	public fun <init> (Lhep/dataforge/context/Context;Ljava/util/Set;)V
 	public final fun fetch (Lhep/dataforge/context/PluginFactory;ZLhep/dataforge/meta/Meta;)Lhep/dataforge/context/Plugin;
 	public final fun fetch (Lhep/dataforge/context/PluginFactory;ZLkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Plugin;
 	public static synthetic fun fetch$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;ZLhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
index b675a42b..605e6f8b 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
@@ -28,6 +28,7 @@ public open class Context(
     final override val name: Name,
     public val parent: Context?,
     meta: Meta,
+    plugins: Set<Plugin> = emptySet(),
 ) : Named, MetaRepr, Provider, CoroutineScope {
 
     /**
@@ -47,32 +48,7 @@ public open class Context(
     /**
      * A [PluginManager] for current context
      */
-    public val plugins: PluginManager = PluginManager(this)
-
-    @Deprecated("To be removed in favor of immutable plugins")
-    private val activators = HashSet<Any>()
-
-    /**
-     * Defines if context is used in any kind of active computations. Active context properties and plugins could not be changed
-     */
-    @Deprecated("To be removed in favor of immutable plugins")
-    public val isActive: Boolean = activators.isNotEmpty()
-
-    /**
-     * Mark context as active and used by [activator]
-     */
-    @Deprecated("To be removed in favor of immutable plugins")
-    public fun activate(activator: Any) {
-        activators.add(activator)
-    }
-
-    /**
-     * Mark context unused by [activator]
-     */
-    @Deprecated("To be removed in favor of immutable plugins")
-    public fun deactivate(activator: Any) {
-        activators.remove(activator)
-    }
+    public val plugins: PluginManager by lazy { PluginManager(this, plugins)}
 
     override val defaultTarget: String get() = Plugin.TARGET
 
@@ -104,8 +80,6 @@ public open class Context(
      * Detach all plugins and terminate context
      */
     public open fun close() {
-        @Suppress("DEPRECATION")
-        if (isActive) error("Can't close active context")
         //detach all plugins
         plugins.forEach { it.detach() }
     }
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
index 75bd6c5d..b742474c 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
@@ -8,7 +8,7 @@ import hep.dataforge.names.toName
  */
 @DFBuilder
 public class ContextBuilder(private val parent: Context = Global, public var name: String = "@anonymous") {
-    private val plugins = ArrayList<Plugin>()
+    private val plugins = HashSet<Plugin>()
     private var meta = MetaBuilder()
 
     public fun properties(action: MetaBuilder.() -> Unit) {
@@ -20,9 +20,12 @@ public class ContextBuilder(private val parent: Context = Global, public var nam
     }
 
     @OptIn(DFExperimental::class)
-    public fun plugin(tag: PluginTag, metaBuilder: MetaBuilder.() -> Unit = {}) {
-        val factory = parent.gatherInSequence<PluginFactory<*>>(PluginFactory.TYPE).values
+    private fun findPluginFactory(tag: PluginTag): PluginFactory<*> =
+        parent.gatherInSequence<PluginFactory<*>>(PluginFactory.TYPE).values
             .find { it.tag.matches(tag) } ?: error("Can't resolve plugin factory for $tag")
+
+    public fun plugin(tag: PluginTag, metaBuilder: MetaBuilder.() -> Unit = {}) {
+        val factory = findPluginFactory(tag)
         val plugin = factory.invoke(Meta(metaBuilder), parent)
         plugins.add(plugin)
     }
@@ -36,10 +39,6 @@ public class ContextBuilder(private val parent: Context = Global, public var nam
     }
 
     public fun build(): Context {
-        return Context(name.toName(), parent, meta.seal()).apply {
-            this@ContextBuilder.plugins.forEach {
-                plugins.load(it)
-            }
-        }
+        return Context(name.toName(), parent, meta.seal(), plugins)
     }
 }
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
index cdae4f53..3e9def85 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
@@ -16,21 +16,24 @@ public interface PluginFactory<T : Plugin> : Factory<T> {
     }
 }
 
-
 /**
  * The manager for plugin system. Should monitor plugin dependencies and locks.
  *
  * @property context A context for this plugin manager
  * @author Alexander Nozik
  */
-public class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
+public class PluginManager(override val context: Context, plugins: Set<Plugin>) : ContextAware, Iterable<Plugin> {
 
     //TODO refactor to read-only container
 
     /**
      * A set of loaded plugins
      */
-    private val plugins = HashSet<Plugin>()
+    private val plugins: HashSet<Plugin> = HashSet(plugins)
+
+    init {
+        plugins.forEach { it.attach(context) }
+    }
 
     /**
      * A [PluginManager] of parent context if it is present
@@ -56,7 +59,6 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
     public fun find(inherit: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? =
         list(inherit).find(predicate)
 
-
     /**
      * Find a loaded plugin via its tag
      *
@@ -66,7 +68,6 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
     public operator fun get(tag: PluginTag, inherit: Boolean = true): Plugin? =
         find(inherit) { tag.matches(it.tag) }
 
-
     /**
      * Find a loaded plugin via its class. This method does not check if the result is unique and just returns first
      * plugin matching the class condition.
@@ -96,10 +97,8 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
      * @return
      */
     public fun <T : Plugin> load(plugin: T): T {
-        if (context.isActive) error("Can't load plugin into active context")
-
         if (get(plugin::class, plugin.tag, recursive = false) != null) {
-            error("Plugin of type ${plugin::class} already exists in ${context.name}")
+            error("Plugin with tag ${plugin.tag} already exists in ${context.name}")
         } else {
             for (tag in plugin.dependsOn()) {
                 fetch(tag, true)
@@ -125,8 +124,6 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
      * Remove a plugin from [PluginManager]
      */
     public fun remove(plugin: Plugin) {
-        if (context.isActive) error("Can't remove plugin from active context")
-
         if (plugins.contains(plugin)) {
             logger.info { "Removing plugin ${plugin.name} from ${context.name}" }
             plugin.detach()
@@ -136,7 +133,6 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
 
     /**
      * Get an existing plugin with given meta or load new one using provided factory
-     *
      */
     public fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = Meta.EMPTY): T {
         val loaded = get(factory.type, factory.tag, recursive)
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
index b45a662c..b9aaad18 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
@@ -45,25 +45,23 @@ public interface Workspace : ContextAware, Provider {
      * Invoke a task in the workspace utilizing caching if possible
      */
     public fun <R : Any> run(task: Task<R>, config: Meta): DataNode<R> {
-        context.activate(this)
-        try {
-            val model = task.build(this, config)
-            task.validate(model)
-            return task.run(this, model)
-        } finally {
-            context.deactivate(this)
-        }
+        val model = task.build(this, config)
+        task.validate(model)
+        return task.run(this, model)
     }
 
     public companion object {
         public const val TYPE: String = "workspace"
-        public operator fun invoke(parent: Context = Global, block: SimpleWorkspaceBuilder.() -> Unit): SimpleWorkspace =
+        public operator fun invoke(
+            parent: Context = Global,
+            block: SimpleWorkspaceBuilder.() -> Unit,
+        ): SimpleWorkspace =
             SimpleWorkspaceBuilder(parent).apply(block).build()
     }
 }
 
 public fun Workspace.run(task: Task<*>, target: String): DataNode<Any> {
-    val meta = targets[target] ?: error("A target with name $target not found in ${this}")
+    val meta = targets[target] ?: error("A target with name $target not found in $this")
     return run(task, meta)
 }
 
@@ -77,5 +75,5 @@ public fun Workspace.run(task: String, meta: Meta): DataNode<Any> =
 public fun Workspace.run(task: String, block: MetaBuilder.() -> Unit = {}): DataNode<Any> =
     run(task, Meta(block))
 
-public fun <T: Any> Workspace.run(task: Task<T>, metaBuilder: MetaBuilder.() -> Unit = {}): DataNode<T> =
+public fun <T : Any> Workspace.run(task: Task<T>, metaBuilder: MetaBuilder.() -> Unit = {}): DataNode<T> =
     run(task, Meta(metaBuilder))
\ No newline at end of file

From d68fbfd8a5fc9e55e433ed409e544b0e0caa81c4 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Wed, 11 Nov 2020 10:54:52 +0300
Subject: [PATCH 33/40] Descriptor in SchemeSpec

---
 build.gradle.kts                              |  2 +-
 dataforge-meta/api/dataforge-meta.api         | 10 ++++++----
 .../kotlin/hep/dataforge/meta/Scheme.kt       | 20 +++++++++++++------
 3 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/build.gradle.kts b/build.gradle.kts
index 67b8fec3..3229c409 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,7 +2,7 @@ plugins {
     id("ru.mipt.npm.project")
 }
 
-val dataforgeVersion by extra("0.2.0-dev-6")
+val dataforgeVersion by extra("0.2.0-dev-7")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api
index 743f482a..f946f881 100644
--- a/dataforge-meta/api/dataforge-meta.api
+++ b/dataforge-meta/api/dataforge-meta.api
@@ -479,11 +479,11 @@ public class hep/dataforge/meta/Scheme : hep/dataforge/meta/Configurable, hep/da
 	public fun <init> ()V
 	public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
 	public synthetic fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-	public fun getConfig ()Lhep/dataforge/meta/Config;
+	public final fun getConfig ()Lhep/dataforge/meta/Config;
 	public final fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
 	public fun getDefaultLayer ()Lhep/dataforge/meta/Meta;
 	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
-	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public final fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
 	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
 	public final fun isEmpty ()Z
 	public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
@@ -499,9 +499,11 @@ public final class hep/dataforge/meta/SchemeKt {
 	public static synthetic fun toScheme$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/Configurable;
 }
 
-public class hep/dataforge/meta/SchemeSpec : hep/dataforge/meta/Specification {
+public class hep/dataforge/meta/SchemeSpec : hep/dataforge/meta/Specification, hep/dataforge/meta/descriptors/Described {
 	public fun <init> (Lkotlin/jvm/functions/Function0;)V
-	public fun <init> (Lkotlin/jvm/functions/Function2;)V
+	public fun <init> (Lkotlin/jvm/functions/Function3;)V
+	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
 	public synthetic fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
 	public fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
 }
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
index a85e464f..7d982404 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
@@ -12,12 +12,16 @@ import hep.dataforge.names.asName
 public open class Scheme(
     config: Config = Config(),
     internal var default: ItemProvider? = null,
-    override val descriptor: NodeDescriptor? = null,
+    descriptor: NodeDescriptor? = null,
 ) : Configurable, Described, MetaRepr {
 
     override var config: Config = config
         internal set
 
+    override var descriptor: NodeDescriptor? = descriptor
+        internal set
+
+
     public fun getDefaultItem(name: Name): MetaItem<*>? {
         return default?.getItem(name) ?: descriptor?.get(name)?.defaultItem()
     }
@@ -79,13 +83,14 @@ public inline operator fun <T : Scheme> T.invoke(block: T.() -> Unit): T = apply
  * A specification for simplified generation of wrappers
  */
 public open class SchemeSpec<T : Scheme>(
-    private val builder: (config: Config, defaultProvider: ItemProvider) -> T,
-) : Specification<T> {
+    private val builder: (config: Config, defaultProvider: ItemProvider, descriptor: NodeDescriptor?) -> T,
+) : Specification<T>, Described {
 
-    public constructor(emptyBuilder: () -> T) : this({ config: Config, defaultProvider: ItemProvider ->
+    public constructor(emptyBuilder: () -> T) : this({ config: Config, defaultProvider: ItemProvider, descriptor: NodeDescriptor? ->
         emptyBuilder().apply {
             this.config = config
             this.default = defaultProvider
+            this.descriptor = descriptor
         }
     })
 
@@ -93,10 +98,13 @@ public open class SchemeSpec<T : Scheme>(
      * If the provided [Meta] is a [Config] use it as a scheme base, otherwise use it as default.
      */
     override fun wrap(meta: Meta, defaultProvider: ItemProvider): T = if (meta is Config) {
-        builder(meta, defaultProvider)
+        builder(meta, defaultProvider, descriptor)
     } else {
-        builder(Config(), meta.withDefault(defaultProvider))
+        builder(Config(), meta.withDefault(defaultProvider), descriptor)
     }
+
+    //TODO Generate descriptor from Scheme class
+    override val descriptor: NodeDescriptor? get() = null
 }
 
 ///**

From 1284aa9f2e69116e867f0e26159303a22e6362cf Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Wed, 11 Nov 2020 13:37:02 +0300
Subject: [PATCH 34/40] Configurable is no longer MutableItemProvider. All
 functionality moved to Scheme

---
 dataforge-meta/api/dataforge-meta.api         | 21 ++++++-------------
 .../kotlin/hep/dataforge/meta/Configurable.kt | 14 +------------
 .../hep/dataforge/meta/MutableItemDelegate.kt |  4 ----
 .../kotlin/hep/dataforge/meta/Scheme.kt       |  6 +++---
 4 files changed, 10 insertions(+), 35 deletions(-)

diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api
index f946f881..031cb33d 100644
--- a/dataforge-meta/api/dataforge-meta.api
+++ b/dataforge-meta/api/dataforge-meta.api
@@ -38,15 +38,8 @@ public final class hep/dataforge/meta/ConfigKt {
 	public static final fun get (Lhep/dataforge/meta/Config;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
 }
 
-public abstract interface class hep/dataforge/meta/Configurable : hep/dataforge/meta/MutableItemProvider {
+public abstract interface class hep/dataforge/meta/Configurable {
 	public abstract fun getConfig ()Lhep/dataforge/meta/Config;
-	public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
-	public abstract fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
-}
-
-public final class hep/dataforge/meta/Configurable$DefaultImpls {
-	public static fun getItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
-	public static fun setItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
 }
 
 public final class hep/dataforge/meta/ConfigurableKt {
@@ -414,10 +407,8 @@ public final class hep/dataforge/meta/MutableItemDelegateKt {
 	public static final fun stringList (Lhep/dataforge/meta/MutableItemProvider;[Ljava/lang/String;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
 	public static synthetic fun stringList$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
 	public static synthetic fun stringList$default (Lhep/dataforge/meta/MutableItemProvider;[Ljava/lang/String;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
-	public static final fun value (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
 	public static final fun value (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
 	public static final fun value (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
-	public static synthetic fun value$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
 	public static synthetic fun value$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
 	public static synthetic fun value$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
 }
@@ -475,15 +466,15 @@ public final class hep/dataforge/meta/ObservableMeta$DefaultImpls {
 	public static fun toMeta (Lhep/dataforge/meta/ObservableMeta;)Lhep/dataforge/meta/Meta;
 }
 
-public class hep/dataforge/meta/Scheme : hep/dataforge/meta/Configurable, hep/dataforge/meta/MetaRepr, hep/dataforge/meta/descriptors/Described {
+public class hep/dataforge/meta/Scheme : hep/dataforge/meta/Configurable, hep/dataforge/meta/MetaRepr, hep/dataforge/meta/MutableItemProvider, hep/dataforge/meta/descriptors/Described {
 	public fun <init> ()V
 	public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
 	public synthetic fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-	public final fun getConfig ()Lhep/dataforge/meta/Config;
+	public fun getConfig ()Lhep/dataforge/meta/Config;
 	public final fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
 	public fun getDefaultLayer ()Lhep/dataforge/meta/Meta;
 	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
-	public final fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
 	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
 	public final fun isEmpty ()Z
 	public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
@@ -495,8 +486,8 @@ public class hep/dataforge/meta/Scheme : hep/dataforge/meta/Configurable, hep/da
 public final class hep/dataforge/meta/SchemeKt {
 	public static final fun asScheme (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Scheme;
 	public static final fun invoke (Lhep/dataforge/meta/Scheme;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
-	public static final fun toScheme (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
-	public static synthetic fun toScheme$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/Configurable;
+	public static final fun toScheme (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+	public static synthetic fun toScheme$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
 }
 
 public class hep/dataforge/meta/SchemeSpec : hep/dataforge/meta/Specification, hep/dataforge/meta/descriptors/Described {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
index 2308bef2..764ee1ea 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
@@ -6,23 +6,11 @@ import kotlin.properties.ReadWriteProperty
 /**
  * A container that holds a [Config].
  */
-public interface Configurable : MutableItemProvider {
+public interface Configurable {
     /**
      * Backing config
      */
     public val config: Config
-
-    /**
-     * Get a property with default
-     */
-    override fun getItem(name: Name): MetaItem<*>? = config[name]
-
-    /**
-     * Set a configurable property
-     */
-    override fun setItem(name: Name, item: MetaItem<*>?) {
-        config.setItem(name, item)
-    }
 }
 
 
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
index 4d33bea7..e7fb8446 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
@@ -118,10 +118,6 @@ public inline fun <reified E : Enum<E>> MutableItemProvider.enum(
 public inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
     item(key).convert(reader = { it?.let { it.node as M } }, writer = { it?.let { MetaItem.NodeItem(it) } })
 
-
-public fun Configurable.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
-    item(key).convert(MetaConverter.value)
-
 /* Number delegates */
 
 public fun MutableItemProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> =
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
index 7d982404..b9e777e7 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
@@ -13,7 +13,7 @@ public open class Scheme(
     config: Config = Config(),
     internal var default: ItemProvider? = null,
     descriptor: NodeDescriptor? = null,
-) : Configurable, Described, MetaRepr {
+) : Configurable, MutableItemProvider, Described, MetaRepr {
 
     override var config: Config = config
         internal set
@@ -44,7 +44,7 @@ public open class Scheme(
      */
     override fun setItem(name: Name, item: MetaItem<*>?) {
         if (validateItem(name, item)) {
-            super.setItem(name, item)
+            config.setItem(name, item)
         } else {
             error("Validation failed for property $name with value $item")
         }
@@ -120,5 +120,5 @@ public open class SchemeSpec<T : Scheme>(
 
 public fun Meta.asScheme(): Scheme = Scheme(this.asConfig(), null, null)
 
-public fun <T : Configurable> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit = {}): T =
+public fun <T : MutableItemProvider> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit = {}): T =
     spec.wrap(this).apply(block)

From 920366388d2db537ba211d946127d1ea171bec05 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Fri, 13 Nov 2020 19:44:07 +0300
Subject: [PATCH 35/40] Changelog update

---
 CHANGELOG.md                                                  | 1 +
 .../src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt  | 2 +-
 .../kotlin/hep/dataforge/meta/MutableItemDelegate.kt          | 4 +++-
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index baec4747..2451503f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@
 - Provider provides an empty map instead of error by default
 - Hidden delegates hierarchy in favor of stdlib properties
 - Removed io depdendency from `dataforge-output`. Replaced Output by Appendable.
+- Configurable is no longer MutableItemProvider. All functionality moved to Scheme.
 
 ### Deprecated
 - Context activation API
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
index 2201aa8a..eab2573f 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
@@ -45,7 +45,7 @@ public fun <R> ItemDelegate.convert(
     this@convert.getValue(thisRef, property).let(reader)
 }
 
-/* Read-only delegates for Metas */
+/* Read-only delegates for [ItemProvider] */
 
 /**
  * A property delegate that uses custom key
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
index e7fb8446..32a7c7d4 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
@@ -71,7 +71,9 @@ public fun <R> MutableItemDelegate.convert(
     }
 }
 
-/* Read-write delegates */
+
+
+/* Read-write delegates for [MutableItemProvider] */
 
 /**
  * A property delegate that uses custom key

From 0a77f729ec735fa9347d5d4f79c3c77141c4a14c Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Fri, 20 Nov 2020 14:47:18 +0300
Subject: [PATCH 36/40] Fixed inline `invloke` on `Specification`

---
 CHANGELOG.md                                  |  2 +
 build.gradle.kts                              |  2 +-
 .../hep/dataforge/meta/Specification.kt       |  4 +-
 .../api/dataforge-output-html.api             | 26 ------
 .../dataforge-output-html/build.gradle.kts    | 16 ----
 .../hep/dataforge/output/html/HtmlRenderer.kt | 82 -------------------
 .../hep/dataforge/output/OutputManager.kt     | 19 ++---
 .../kotlin/hep/dataforge/output/Renderer.kt   |  4 +-
 .../hep/dataforge/output/TextRenderer.kt      |  4 +
 dataforge-workspace/build.gradle.kts          |  1 -
 .../hep/dataforge/workspace/fileData.kt       | 10 +--
 settings.gradle.kts                           |  3 +-
 12 files changed, 23 insertions(+), 150 deletions(-)
 delete mode 100644 dataforge-output/dataforge-output-html/api/dataforge-output-html.api
 delete mode 100644 dataforge-output/dataforge-output-html/build.gradle.kts
 delete mode 100644 dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2451503f..a1a6bc0f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,9 +14,11 @@
 
 ### Deprecated
 - Context activation API
+- TextRenderer
 
 ### Removed
 - Functional server prototype
+- `dataforge-output` module
 
 ### Fixed
 - Global context CoroutineScope resolution
diff --git a/build.gradle.kts b/build.gradle.kts
index 3229c409..5068b5be 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,7 +2,7 @@ plugins {
     id("ru.mipt.npm.project")
 }
 
-val dataforgeVersion by extra("0.2.0-dev-7")
+val dataforgeVersion by extra("0.2.0-dev-8")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
index 03bc36b6..e4542933 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
@@ -18,10 +18,10 @@ public interface Specification<T : MutableItemProvider> {
     public fun wrap(meta: Meta, defaultProvider: ItemProvider = ItemProvider.EMPTY): T
 }
 
-public operator fun <T : MutableItemProvider> Specification<T>.invoke(action: T.() -> Unit): T = empty().apply(action)
-
 public fun <T : MutableItemProvider> Specification<T>.empty(): T = wrap(Config())
 
+public inline operator fun <T : MutableItemProvider> Specification<T>.invoke(action: T.() -> Unit): T = empty().apply(action)
+
 /**
  * Update given configuration using given type as a builder
  */
diff --git a/dataforge-output/dataforge-output-html/api/dataforge-output-html.api b/dataforge-output/dataforge-output-html/api/dataforge-output-html.api
deleted file mode 100644
index 964c6971..00000000
--- a/dataforge-output/dataforge-output-html/api/dataforge-output-html.api
+++ /dev/null
@@ -1,26 +0,0 @@
-public final class hep/dataforge/output/html/DefaultHtmlBuilder : hep/dataforge/output/html/HtmlBuilder {
-	public static final field INSTANCE Lhep/dataforge/output/html/DefaultHtmlBuilder;
-	public fun getPriority ()I
-	public fun getType ()Lkotlin/reflect/KClass;
-	public fun render (Lkotlinx/html/FlowContent;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-}
-
-public abstract interface class hep/dataforge/output/html/HtmlBuilder {
-	public static final field Companion Lhep/dataforge/output/html/HtmlBuilder$Companion;
-	public static final field HTML_CONVERTER_TYPE Ljava/lang/String;
-	public abstract fun getPriority ()I
-	public abstract fun getType ()Lkotlin/reflect/KClass;
-	public abstract fun render (Lkotlinx/html/FlowContent;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-}
-
-public final class hep/dataforge/output/html/HtmlBuilder$Companion {
-	public static final field HTML_CONVERTER_TYPE Ljava/lang/String;
-}
-
-public final class hep/dataforge/output/html/HtmlRenderer : hep/dataforge/output/Renderer {
-	public fun <init> (Lhep/dataforge/context/Context;Lkotlinx/html/TagConsumer;)V
-	public fun getContext ()Lhep/dataforge/context/Context;
-	public fun getLogger ()Lmu/KLogger;
-	public fun render (Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
-}
-
diff --git a/dataforge-output/dataforge-output-html/build.gradle.kts b/dataforge-output/dataforge-output-html/build.gradle.kts
deleted file mode 100644
index 4b8bdbda..00000000
--- a/dataforge-output/dataforge-output-html/build.gradle.kts
+++ /dev/null
@@ -1,16 +0,0 @@
-plugins {
-    id("ru.mipt.npm.mpp")
-}
-
-val htmlVersion by rootProject.extra("0.7.2")
-
-kotlin {
-    sourceSets {
-        val commonMain by getting {
-            dependencies {
-                api(project(":dataforge-output"))
-                api("org.jetbrains.kotlinx:kotlinx-html:$htmlVersion")
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt b/dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt
deleted file mode 100644
index 25cf2116..00000000
--- a/dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-package hep.dataforge.output.html
-
-import hep.dataforge.context.Context
-import hep.dataforge.meta.DFExperimental
-import hep.dataforge.meta.Meta
-import hep.dataforge.output.Output
-import hep.dataforge.output.Renderer
-import hep.dataforge.output.TextFormat
-import hep.dataforge.output.html.HtmlBuilder.Companion.HTML_CONVERTER_TYPE
-import hep.dataforge.provider.Type
-import hep.dataforge.provider.top
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.html.FlowContent
-import kotlinx.html.TagConsumer
-import kotlinx.html.p
-import kotlin.reflect.KClass
-
-
-@DFExperimental
-public class HtmlRenderer<T : Any>(override val context: Context, private val consumer: TagConsumer<*>) : Renderer<T> {
-    private val cache = HashMap<KClass<*>, HtmlBuilder<*>>()
-
-    /**
-     * Find the first [TextFormat] matching the given object type.
-     */
-    override fun render(obj: T, meta: Meta) {
-
-        val builder: HtmlBuilder<*> = if (obj is CharSequence) {
-            DefaultHtmlBuilder
-        } else {
-            val value = cache[obj::class]
-            if (value == null) {
-                val answer =
-                    context.top<HtmlBuilder<*>>(HTML_CONVERTER_TYPE).values.firstOrNull { it.type.isInstance(obj) }
-                if (answer != null) {
-                    cache[obj::class] = answer
-                    answer
-                } else {
-                    DefaultHtmlBuilder
-                }
-            } else {
-                value
-            }
-        }
-        context.launch(Dispatchers.Output) {
-            @Suppress("UNCHECKED_CAST")
-            (builder as HtmlBuilder<T>).run { render(obj) }
-        }
-    }
-}
-
-/**
- * A text or binary renderer based on [Renderer]
- */
-@Type(HTML_CONVERTER_TYPE)
-public interface HtmlBuilder<T : Any> {
-    /**
-     * The priority of this renderer compared to other renderers
-     */
-    public val priority: Int
-
-    /**
-     * The type of the content served by this renderer
-     */
-    public val type: KClass<T>
-
-    public suspend fun FlowContent.render(obj: T)
-
-    public companion object {
-        public const val HTML_CONVERTER_TYPE: String = "dataforge.htmlBuilder"
-    }
-}
-
-public object DefaultHtmlBuilder : HtmlBuilder<Any> {
-    override val priority: Int = Int.MAX_VALUE
-    override val type: KClass<Any> = Any::class
-
-    override suspend fun FlowContent.render(obj: Any) {
-        p { +obj.toString() }
-    }
-}
\ No newline at end of file
diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt
index f0c71525..e606c9b7 100644
--- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt
+++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt
@@ -19,7 +19,7 @@ public interface OutputManager {
      * @param name represents the name inside the node.
      * @param meta configuration for [Renderer] (not for rendered object)
      */
-    public operator fun <T : Any> get(
+    public fun <T : Any> getOutputContainer(
         type: KClass<out T>,
         name: Name,
         stage: Name = Name.EMPTY,
@@ -35,37 +35,30 @@ public val Context.output: OutputManager get() = plugins.get() ?: ConsoleOutputM
 /**
  * Get an output with given [name], [stage] and reified content type
  */
-public inline operator fun <reified T : Any> OutputManager.get(
+public inline fun <reified T : Any> OutputManager.getOutputContainer(
     name: Name,
     stage: Name = Name.EMPTY,
     meta: Meta = Meta.EMPTY
 ): Renderer<T> {
-    return get(T::class, name, stage, meta)
+    return getOutputContainer(T::class, name, stage, meta)
 }
 
 /**
  * Directly render an object using the most suitable renderer
  */
 public fun OutputManager.render(obj: Any, name: Name, stage: Name = Name.EMPTY, meta: Meta = Meta.EMPTY): Unit =
-    get(obj::class, name, stage).render(obj, meta)
+    getOutputContainer(obj::class, name, stage).render(obj, meta)
 
 /**
  * System console output.
  * The [CONSOLE_RENDERER] is used when no other [OutputManager] is provided.
  */
-public val CONSOLE_RENDERER: Renderer<Any> = object : Renderer<Any> {
-    override fun render(obj: Any, meta: Meta) {
-        println(obj)
-    }
-
-    override val context: Context get() = Global
-
-}
+public val CONSOLE_RENDERER: Renderer<Any> = Renderer { obj, meta -> println(obj) }
 
 public class ConsoleOutputManager : AbstractPlugin(), OutputManager {
     override val tag: PluginTag get() = ConsoleOutputManager.tag
 
-    override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Renderer<T> = CONSOLE_RENDERER
+    override fun <T : Any> getOutputContainer(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Renderer<T> = CONSOLE_RENDERER
 
     public companion object : PluginFactory<ConsoleOutputManager> {
         override val tag: PluginTag = PluginTag("output.console", group = DATAFORGE_GROUP)
diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt
index 6e3bee19..ebcb03ba 100644
--- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt
+++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt
@@ -10,12 +10,12 @@ import hep.dataforge.meta.Meta
  * based on its configuration and provided meta
  *
  */
-public interface Renderer<in T : Any> : ContextAware {
+public fun interface Renderer<in T : Any> {
     /**
      * Render specific object with configuration.
      *
      * By convention actual render is called in asynchronous mode, so this method should never
      * block execution
      */
-    public fun render(obj: T, meta: Meta = Meta.EMPTY)
+    public fun render(obj: T, meta: Meta)
 }
diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
index 9249de41..235cdab2 100644
--- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
+++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
@@ -8,12 +8,14 @@ import hep.dataforge.provider.top
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlin.reflect.KClass
+import kotlin.reflect.KType
 
 
 /**
  * A text or binary renderer based on [Output]
  */
 @Type(TEXT_RENDERER_TYPE)
+@Deprecated("Bad design")
 public interface TextFormat {
     /**
      * The priority of this renderer compared to other renderers
@@ -31,6 +33,7 @@ public interface TextFormat {
     }
 }
 
+@Deprecated("Bad design")
 public object DefaultTextFormat : TextFormat {
     override val priority: Int = Int.MAX_VALUE
     override val type: KClass<*> = Any::class
@@ -43,6 +46,7 @@ public object DefaultTextFormat : TextFormat {
 /**
  * A text-based renderer
  */
+@Deprecated("Bad design")
 public class TextRenderer(override val context: Context, private val output: Appendable) : Renderer<Any> {
     private val cache = HashMap<KClass<*>, TextFormat>()
 
diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts
index a18ddba6..2bb03cec 100644
--- a/dataforge-workspace/build.gradle.kts
+++ b/dataforge-workspace/build.gradle.kts
@@ -9,7 +9,6 @@ kotlin {
             dependencies {
                 api(project(":dataforge-context"))
                 api(project(":dataforge-data"))
-                api(project(":dataforge-output"))
                 api(project(":dataforge-io"))
             }
         }
diff --git a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt b/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt
index 4631dc09..97ae77e6 100644
--- a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt
+++ b/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt
@@ -36,7 +36,7 @@ private fun newZFS(path: Path): FileSystem {
  * @param metaFileFormat the meta format for override
  */
 @DFExperimental
-fun <T : Any> IOPlugin.readDataFile(
+public fun <T : Any> IOPlugin.readDataFile(
     path: Path,
     type: KClass<out T>,
     formatResolver: FileFormatResolver<T>
@@ -47,7 +47,7 @@ fun <T : Any> IOPlugin.readDataFile(
 }
 
 @DFExperimental
-inline fun <reified T : Any> IOPlugin.readDataFile(path: Path): Data<T> =
+public inline fun <reified T : Any> IOPlugin.readDataFile(path: Path): Data<T> =
     readDataFile(path, T::class) { _, _ ->
         resolveIOFormat<T>() ?: error("Can't resolve IO format for ${T::class}")
     }
@@ -56,7 +56,7 @@ inline fun <reified T : Any> IOPlugin.readDataFile(path: Path): Data<T> =
  * Add file/directory-based data tree item
  */
 @DFExperimental
-fun <T : Any> DataTreeBuilder<T>.file(
+public fun <T : Any> DataTreeBuilder<T>.file(
     plugin: IOPlugin,
     path: Path,
     formatResolver: FileFormatResolver<T>
@@ -109,7 +109,7 @@ fun <T : Any> IOPlugin.readDataDirectory(
 }
 
 @DFExperimental
-inline fun <reified T : Any> IOPlugin.readDataDirectory(path: Path): DataNode<T> =
+public inline fun <reified T : Any> IOPlugin.readDataDirectory(path: Path): DataNode<T> =
     readDataDirectory(path, T::class) { _, _ ->
         resolveIOFormat<T>() ?: error("Can't resolve IO format for ${T::class}")
     }
@@ -118,7 +118,7 @@ inline fun <reified T : Any> IOPlugin.readDataDirectory(path: Path): DataNode<T>
  * Write data tree to existing directory or create a new one using default [java.nio.file.FileSystem] provider
  */
 @DFExperimental
-suspend fun <T : Any> IOPlugin.writeDataDirectory(
+public suspend fun <T : Any> IOPlugin.writeDataDirectory(
     path: Path,
     node: DataNode<T>,
     format: IOFormat<T>,
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 1dac01d4..e8b3eafe 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -30,8 +30,7 @@ include(
     ":dataforge-io:dataforge-io-yaml",
     ":dataforge-context",
     ":dataforge-data",
-    ":dataforge-output",
-    ":dataforge-output:dataforge-output-html",
+//    ":dataforge-output",
     ":dataforge-tables",
     ":dataforge-workspace",
     ":dataforge-scripting"

From 2eb5fe03cd8780d4bea174eb84ca997dfc11253d Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Fri, 20 Nov 2020 16:58:27 +0300
Subject: [PATCH 37/40] Fix scheme initialization

---
 .../kotlin/hep/dataforge/data/DataFilter.kt   |  2 +-
 .../kotlin/hep/dataforge/io/EnvelopeParts.kt  |  2 +-
 dataforge-meta/api/dataforge-meta.api         | 24 +++++++---
 .../kotlin/hep/dataforge/meta/Scheme.kt       | 24 ++++++----
 .../hep/dataforge/meta/Specification.kt       | 47 +++++++++++--------
 .../hep/dataforge/meta/SpecificationTest.kt   | 10 ++--
 6 files changed, 68 insertions(+), 41 deletions(-)

diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
index 8369080e..df19acd0 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
@@ -44,7 +44,7 @@ public fun <T : Any> DataNode<T>.filter(filter: DataFilter): DataNode<T> {
 /**
  * Filter data using [DataFilter] specification
  */
-public fun <T : Any> DataNode<T>.filter(filter: Meta): DataNode<T> = filter(DataFilter.wrap(filter))
+public fun <T : Any> DataNode<T>.filter(filter: Meta): DataNode<T> = filter(DataFilter.read(filter))
 
 /**
  * Filter data using [DataFilter] builder
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt
index 805a91b3..cae87229 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt
@@ -88,7 +88,7 @@ public fun Envelope.parts(): EnvelopeParts {
     if (data == null) return emptyList()
     //TODO add zip folder reader
     val parts = meta.getIndexed(PARTS_KEY).values.mapNotNull { it.node }.map {
-        PartDescriptor.wrap(it)
+        PartDescriptor.read(it)
     }
     return if (parts.isEmpty()) {
         listOf(EnvelopePart(data!!, meta[MULTIPART_KEY].node))
diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api
index 031cb33d..f4b8d3ed 100644
--- a/dataforge-meta/api/dataforge-meta.api
+++ b/dataforge-meta/api/dataforge-meta.api
@@ -493,10 +493,16 @@ public final class hep/dataforge/meta/SchemeKt {
 public class hep/dataforge/meta/SchemeSpec : hep/dataforge/meta/Specification, hep/dataforge/meta/descriptors/Described {
 	public fun <init> (Lkotlin/jvm/functions/Function0;)V
 	public fun <init> (Lkotlin/jvm/functions/Function3;)V
+	public synthetic fun empty ()Lhep/dataforge/meta/MutableItemProvider;
+	public fun empty ()Lhep/dataforge/meta/Scheme;
 	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
 	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
-	public synthetic fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
-	public fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
+	public synthetic fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+	public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
+	public synthetic fun read (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+	public fun read (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
+	public synthetic fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+	public fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
 }
 
 public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractMetaNode {
@@ -504,19 +510,24 @@ public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractMe
 }
 
 public abstract interface class hep/dataforge/meta/Specification {
-	public abstract fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+	public abstract fun empty ()Lhep/dataforge/meta/MutableItemProvider;
+	public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+	public abstract fun read (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+	public abstract fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
 }
 
 public final class hep/dataforge/meta/Specification$DefaultImpls {
-	public static synthetic fun wrap$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
+	public static fun empty (Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
+	public static fun invoke (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+	public static synthetic fun read$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
+	public static fun wrap (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+	public static synthetic fun wrap$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
 }
 
 public final class hep/dataforge/meta/SpecificationKt {
 	public static final fun configSpec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
 	public static final fun configure (Lhep/dataforge/meta/MetaRepr;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaRepr;
 	public static final fun createStyle (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Meta;
-	public static final fun empty (Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
-	public static final fun invoke (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
 	public static final fun spec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
 	public static final fun spec (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Scheme;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
 	public static final fun spec (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
@@ -524,7 +535,6 @@ public final class hep/dataforge/meta/SpecificationKt {
 	public static synthetic fun spec$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
 	public static final fun update (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
 	public static final fun update (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
-	public static final fun wrap (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MutableItemProvider;
 }
 
 public abstract interface class hep/dataforge/meta/descriptors/Described {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
index b9e777e7..1fc74316 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
@@ -16,7 +16,10 @@ public open class Scheme(
 ) : Configurable, MutableItemProvider, Described, MetaRepr {
 
     override var config: Config = config
-        internal set
+        internal set(value) {
+            //Fix problem with `init` blocks in specifications
+            field = value.apply { update(field) }
+        }
 
     override var descriptor: NodeDescriptor? = descriptor
         internal set
@@ -94,17 +97,18 @@ public open class SchemeSpec<T : Scheme>(
         }
     })
 
-    /**
-     * If the provided [Meta] is a [Config] use it as a scheme base, otherwise use it as default.
-     */
-    override fun wrap(meta: Meta, defaultProvider: ItemProvider): T = if (meta is Config) {
-        builder(meta, defaultProvider, descriptor)
-    } else {
+    override fun read(meta: Meta, defaultProvider: ItemProvider): T =
         builder(Config(), meta.withDefault(defaultProvider), descriptor)
+
+    override fun wrap(config: Config, defaultProvider: ItemProvider): T {
+        return builder(config, defaultProvider, descriptor)
     }
 
     //TODO Generate descriptor from Scheme class
     override val descriptor: NodeDescriptor? get() = null
+
+    @Suppress("OVERRIDE_BY_INLINE")
+    final override inline operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
 }
 
 ///**
@@ -118,7 +122,9 @@ public open class SchemeSpec<T : Scheme>(
 //    override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
 //}
 
-public fun Meta.asScheme(): Scheme = Scheme(this.asConfig(), null, null)
+public fun Meta.asScheme(): Scheme = Scheme().apply {
+    config = this@asScheme.asConfig()
+}
 
 public fun <T : MutableItemProvider> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit = {}): T =
-    spec.wrap(this).apply(block)
+    spec.read(this).apply(block)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
index e4542933..05c31dc3 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
@@ -13,27 +13,33 @@ import kotlin.reflect.KProperty
  */
 public interface Specification<T : MutableItemProvider> {
     /**
-     * Wrap generic configuration producing instance of desired type
+     * Read generic read-only meta with this [Specification] producing instance of desired type.
      */
-    public fun wrap(meta: Meta, defaultProvider: ItemProvider = ItemProvider.EMPTY): T
+    public fun read(meta: Meta, defaultProvider: ItemProvider = ItemProvider.EMPTY): T
+
+    /**
+     * Wrap mutable [Config], using it as inner storage (changes to [Specification] are reflected on [Config]
+     */
+    public fun wrap(config: Config, defaultProvider: ItemProvider = ItemProvider.EMPTY): T =
+        read(config as Meta, defaultProvider)
+
+    /**
+     * Generate an empty object
+     */
+    public fun empty(): T = read(Meta.EMPTY)
+
+    /**
+     * A convenience method to use specifications in builders
+     */
+    public operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
 }
 
-public fun <T : MutableItemProvider> Specification<T>.empty(): T = wrap(Config())
-
-public inline operator fun <T : MutableItemProvider> Specification<T>.invoke(action: T.() -> Unit): T = empty().apply(action)
-
 /**
  * Update given configuration using given type as a builder
  */
-public fun <T : MutableItemProvider> Specification<T>.update(meta: Meta, action: T.() -> Unit): T = wrap(meta).apply(action)
+public fun <T : MutableItemProvider> Specification<T>.update(meta: Meta, action: T.() -> Unit): T =
+    read(meta).apply(action)
 
-/**
- * Create a read-only version of
- */
-public fun <T : MutableItemProvider> Specification<T>.wrap(source: Meta): T {
-    val default = source.seal()
-    return wrap(source.asConfig(), default)
-}
 
 /**
  * Apply specified configuration to configurable
@@ -44,7 +50,10 @@ public fun <T : MetaRepr, C : MutableItemProvider, S : Specification<C>> T.confi
 /**
  * Update configuration using given specification
  */
-public fun <C : MutableItemProvider, S : Specification<C>> Configurable.update(spec: S, action: C.() -> Unit): Configurable =
+public fun <C : MutableItemProvider, S : Specification<C>> Configurable.update(
+    spec: S,
+    action: C.() -> Unit,
+): Configurable =
     apply { spec.update(config, action) }
 
 /**
@@ -63,11 +72,11 @@ public fun <T : MutableItemProvider> MetaItem<*>.spec(spec: Specification<T>): T
 public fun <T : MutableItemProvider> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
 
 public fun <T : Scheme> MutableItemProvider.spec(
-    spec: Specification<T>, key: Name? = null
+    spec: Specification<T>, key: Name? = null,
 ): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
     override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
         val name = key ?: property.name.asName()
-        return getItem(name).node?.let { spec.wrap(it) }
+        return getItem(name).node?.let { spec.read(it) }
     }
 
     override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
@@ -79,11 +88,11 @@ public fun <T : Scheme> MutableItemProvider.spec(
 public fun <T : Scheme> MutableItemProvider.spec(
     spec: Specification<T>,
     default: T,
-    key: Name? = null
+    key: Name? = null,
 ): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
     override fun getValue(thisRef: Any?, property: KProperty<*>): T {
         val name = key ?: property.name.asName()
-        return getItem(name).node?.let { spec.wrap(it) } ?: default
+        return getItem(name).node?.let { spec.read(it) } ?: default
     }
 
     override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
index bf73ba8c..587e2049 100644
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
@@ -4,13 +4,15 @@ import kotlin.test.Test
 import kotlin.test.assertEquals
 
 class SpecificationTest {
-    class TestStyled(config: Config, defaultProvider: ItemProvider) :
-        Scheme(config, defaultProvider) {
+    class TestStyled : Scheme() {
         var list by numberList(1, 2, 3)
 
         companion object : Specification<TestStyled> {
-            override fun wrap(meta: Meta, defaultProvider: ItemProvider): TestStyled =
-                TestStyled(meta.asConfig(), defaultProvider)
+            override fun read(meta: Meta, defaultProvider: ItemProvider): TestStyled =
+                TestStyled().apply {
+                    this.config = meta.asConfig()
+
+                }
         }
     }
 

From 167b73df8517d8872b139fd48217cf2cb3466544 Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Wed, 25 Nov 2020 22:18:39 +0300
Subject: [PATCH 38/40] 0.2.0 - RC

---
 build.gradle.kts                                   |  2 +-
 .../kotlin/hep/dataforge/meta/ConfigTest.kt        | 14 ++++++++++++++
 settings.gradle.kts                                |  6 +++---
 3 files changed, 18 insertions(+), 4 deletions(-)
 create mode 100644 dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/ConfigTest.kt

diff --git a/build.gradle.kts b/build.gradle.kts
index 5068b5be..7d138083 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,7 +2,7 @@ plugins {
     id("ru.mipt.npm.project")
 }
 
-val dataforgeVersion by extra("0.2.0-dev-8")
+val dataforgeVersion by extra("0.2.0")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/ConfigTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/ConfigTest.kt
new file mode 100644
index 00000000..5e6341aa
--- /dev/null
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/ConfigTest.kt
@@ -0,0 +1,14 @@
+package hep.dataforge.meta
+
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class ConfigTest {
+    @Test
+    fun testIndexedWrite(){
+        val config = Config()
+        config["a[1].b"] = 1
+        assertEquals(null, config["a.b"].int)
+        assertEquals(1, config["a[1].b"].int)
+    }
+}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index e8b3eafe..1d15b239 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -10,8 +10,8 @@ pluginManagement {
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
 
-    val toolsVersion = "0.6.4-dev-1.4.20-M2"
-    val kotlinVersion = "1.4.20-M2"
+    val toolsVersion = "0.7.0"
+    val kotlinVersion = "1.4.20"
 
     plugins {
         id("ru.mipt.npm.project") version toolsVersion
@@ -27,7 +27,7 @@ pluginManagement {
 include(
     ":dataforge-meta",
     ":dataforge-io",
-    ":dataforge-io:dataforge-io-yaml",
+//    ":dataforge-io:dataforge-io-yaml",
     ":dataforge-context",
     ":dataforge-data",
 //    ":dataforge-output",

From 3a6aef95b1afecd814e2eb17c708d79c305f335d Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Thu, 26 Nov 2020 22:20:25 +0300
Subject: [PATCH 39/40] Bump version

---
 build.gradle.kts  | 2 +-
 gradle.properties | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/build.gradle.kts b/build.gradle.kts
index 7d138083..6f7613e9 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,7 +2,7 @@ plugins {
     id("ru.mipt.npm.project")
 }
 
-val dataforgeVersion by extra("0.2.0")
+val dataforgeVersion by extra("0.2.0-dev-rc")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
diff --git a/gradle.properties b/gradle.properties
index 930bba55..a782b701 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,7 +1,7 @@
 kotlin.code.style=official
 kotlin.parallel.tasks.in.project=true
 kotlin.mpp.enableGranularSourceSetsMetadata=true
-kotlin.native.enableDependencyPropagation=false
+//kotlin.native.enableDependencyPropagation=false
 kotlin.mpp.stability.nowarn=true
 
 org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m

From 2315fb963b9ccb1459e83fef491df3183b18fb6d Mon Sep 17 00:00:00 2001
From: Alexander Nozik <altavir@gmail.com>
Date: Thu, 26 Nov 2020 22:21:29 +0300
Subject: [PATCH 40/40] Patch changelog

---
 CHANGELOG.md     | 12 ++++++++++++
 build.gradle.kts |  2 +-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1a6bc0f..5018fb97 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,18 @@
 ## [Unreleased]
 ### Added
 
+### Changed
+
+### Deprecated
+
+### Removed
+
+### Fixed
+
+### Security
+## [0.2.0]
+### Added
+
 ### Changed
 - Context content resolution refactor
 - Kotlin 1.4.10 (build tools 0.6.0)
diff --git a/build.gradle.kts b/build.gradle.kts
index 6f7613e9..7d138083 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,7 +2,7 @@ plugins {
     id("ru.mipt.npm.project")
 }
 
-val dataforgeVersion by extra("0.2.0-dev-rc")
+val dataforgeVersion by extra("0.2.0")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")