skainet-java-consumer — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited skainet-java-consumer (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Calling SKaiNET from a pure-Java app: which Maven artifacts to depend on, the entry-point classes that were designed to be Java-friendly, idiomatic Java patterns over the sk.ainet.java facade.
.java, not .kt, and they want to use SKaiNET.SKaiNET.context(), SKaiNET.tensor(...), SKaiNET.zeros(...), TensorJavaOps.add(...), etc. from Java.StableHloConverterFactory.createBasic() / createExtended() for HLO export.TokenizerFactory.fromGguf(metadata) to build a tokenizer from a GGUF file.skainet-test-java as canonical usage examples.skainet-inference (and the rest of the consumer plugin) covers it more directly.@JvmStatic members) — the contributor skainet-java-interop skill.skainet-android-integration (its threading rules apply even from Java; the dispatcher just becomes ExecutorService).sk.ainet:skainet-bom:<VERSION> (BOM)sk.ainet.core:skainet-lang-core (DSL types + SKaiNET + TensorJavaOps)sk.ainet.core:skainet-backend-cpu (DirectCpuExecutionContext.create())skainet-io-core + skainet-io-{gguf|onnx|safetensors}skainet-compile-core + skainet-compile-hloThe skainet-test-java consumer module's build.gradle.kts is the canonical reference for the dependency set: SKaiNET/skainet-test/skainet-test-java/build.gradle.kts:9-21.
--enable-preview --add-modules jdk.incubator.vector); only enable those flags if you actually use Vector / preview APIs. or sk.ainet.context.` packages from Java unless absolutely necessary.* The Java entry points are the supported surface.Tensor<*, *>). Don't try to declare Tensor<DType, Float> in Java — the Kotlin * projection collapses to ? and any further generic bounds are awkward.KClass. The SKaiNET factory takes a DType instance and resolves to a KClass<DType> internally.kotlin/sk/ainet/io/... is suspend, Java sees an extra Continuation parameter — that's not supportable from a normal Java caller. Use a Kotlin shim that exposes CompletableFuture<T> or a blocking helper.<dependency> blocks or Gradle if Java + Gradle is the setup).ExecutionContext: ExecutionContext ctx = SKaiNET.context();.SKaiNET.tensor(...) / SKaiNET.zeros(...) / SKaiNET.full(...).TensorJavaOps.<op>(...) — never reach into the Kotlin *.ops field directly.StableHloConverterFactory and TokenizerFactory.Maven `pom.xml` (JVM-only Java consumer):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>sk.ainet</groupId>
<artifactId>skainet-bom</artifactId>
<version>0.20.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>sk.ainet.core</groupId>
<artifactId>skainet-lang-core</artifactId>
</dependency>
<dependency>
<groupId>sk.ainet.core</groupId>
<artifactId>skainet-backend-cpu</artifactId>
</dependency>
<!-- optional: loaders -->
<dependency>
<groupId>sk.ainet.core</groupId>
<artifactId>skainet-io-core</artifactId>
</dependency>
<dependency>
<groupId>sk.ainet.core</groupId>
<artifactId>skainet-io-gguf</artifactId>
</dependency>
</dependencies>Gradle (Java + Gradle, no Kotlin):
dependencies {
implementation(platform("sk.ainet:skainet-bom:0.20.0-SNAPSHOT"))
implementation("sk.ainet.core:skainet-lang-core")
implementation("sk.ainet.core:skainet-backend-cpu")
}
java {
toolchain { languageVersion = JavaLanguageVersion.of(21) }
}Java tensor ops — minimal arithmetic:
package com.example;
import sk.ainet.context.ExecutionContext;
import sk.ainet.java.SKaiNET;
import sk.ainet.java.TensorJavaOps;
import sk.ainet.lang.tensor.Tensor;
import sk.ainet.lang.types.DType;
public class TensorAddDemo {
public static void main(String[] args) {
ExecutionContext ctx = SKaiNET.context();
Tensor<?, ?> a = SKaiNET.tensor(ctx, new int[]{2, 2}, DType.fp32(),
new float[]{1f, 2f, 3f, 4f});
Tensor<?, ?> b = SKaiNET.tensor(ctx, new int[]{2, 2}, DType.fp32(),
new float[]{10f, 20f, 30f, 40f});
Tensor<?, ?> c = TensorJavaOps.add(a, b);
float[] result = c.getData().copyToFloatArray();
for (float v : result) {
System.out.println(v);
}
}
}
// from: SKaiNET/skainet-test/skainet-test-java/src/test/java/sk/ainet/java/TensorJavaOpsTest.java:25-38Default-argument overloads (`@JvmOverloads` from Kotlin gives you these for free):
// Both work — pick the shape that suits the call site
Tensor<?, ?> z3 = SKaiNET.zeros(ctx, new int[]{2, 2}, DType.fp32());
Tensor<?, ?> z2 = SKaiNET.zeros(ctx, new int[]{2, 2}); // dtype defaults to FP32
Tensor<?, ?> r1 = TensorJavaOps.softmax(input); // dim defaults to -1
Tensor<?, ?> r2 = TensorJavaOps.softmax(input, -1);Activation chain:
Tensor<?, ?> logits = TensorJavaOps.matmul(x, w);
Tensor<?, ?> hidden = TensorJavaOps.relu(logits);
Tensor<?, ?> out = TensorJavaOps.softmax(hidden, -1);HLO export (Java consumer of `skainet-compile-hlo`):
import sk.ainet.compile.hlo.StableHloConverter;
import sk.ainet.compile.hlo.StableHloConverterFactory;
StableHloConverter basic = StableHloConverterFactory.createBasic();
StableHloConverter extended = StableHloConverterFactory.createExtended();
// hand a ComputeGraph to one of these to produce StableHLO MLIR text
// from: SKaiNET/skainet-test/skainet-test-java/src/test/java/sk/ainet/java/ReleaseApiJavaTest.javaTokenizer from GGUF metadata:
import sk.ainet.tokenizer.Tokenizer;
import sk.ainet.tokenizer.TokenizerFactory;
import sk.ainet.tokenizer.UnsupportedTokenizerException;
try {
Tokenizer tok = TokenizerFactory.fromGguf(ggufMetadataMap);
int[] ids = tok.encode("Hello SKaiNET");
} catch (UnsupportedTokenizerException e) {
// GGUF didn't carry a recognised tokenizer; fall back to a manual one
}
// from: SKaiNET/skainet-test/skainet-test-java/src/test/java/sk/ainet/java/ReleaseApiJavaTest.javaSpring Boot bean wiring (typical):
@Configuration
public class SkainetConfig {
@Bean(destroyMethod = "")
public ExecutionContext skainetExecutionContext() {
return SKaiNET.context();
}
}
@Service
public class Classifier {
private final ExecutionContext ctx;
public Classifier(ExecutionContext ctx) { this.ctx = ctx; }
public float[] classify(float[] features) {
Tensor<?, ?> x = SKaiNET.tensor(ctx, new int[]{1, features.length}, DType.fp32(), features);
Tensor<?, ?> y = TensorJavaOps.softmax(model.forward(x, ctx), -1); // model is Kotlin-built and exposed
return y.getData().copyToFloatArray();
}
}For models, consumers typically build the Module in a small Kotlin module (the DSL is awkward from Java) and expose the Module<FP32, Float> to the Java service layer. Mixed-language consumer projects are the norm.
../skainet-consumer-setup/SKILL.md.suspend in Kotlin — needs a Kotlin shim) — ../skainet-model-loading/SKILL.md.ExecutorService instead of coroutines) — ../skainet-inference/SKILL.md.skainet-java-interop skill.// WRONG — KClass parameter from Java
SKaiNET.tensor(ctx, new int[]{2, 2}, FP32.class, data); // FP32::class.java is awkward// RIGHT — DType instance
SKaiNET.tensor(ctx, new int[]{2, 2}, DType.fp32(), data);// WRONG — calling Kotlin properties as fields
Tensor<?, ?> a = ...;
int[] dims = a.shape.dimensions; // Tensor.getShape() is the Java view// RIGHT — Java-style accessors
int[] dims = a.getShape().getDimensions();// WRONG — reaching into the Kotlin ops object
Tensor<?, ?> sum = a.getOps().add(a, b); // ops is Tensor<DType, Any?>.ops — generic chaos in Java// RIGHT — go through the facade
Tensor<?, ?> sum = TensorJavaOps.add(a, b);// WRONG — calling a suspend function directly
Tensor<?, ?> loaded = ggufReader.loadTensor("name"); // compiles only via Continuation; runtime mess// RIGHT — write a Kotlin shim that exposes a CompletableFuture or blocking helper
public CompletableFuture<Tensor<?, ?>> loadTensorAsync(String name) {
return GlobalScope.future { ggufReader.loadTensor(name) }
}// WRONG — JVM 8 toolchain
java { toolchain { languageVersion = JavaLanguageVersion.of(8) } }// RIGHT — JVM 11+
java { toolchain { languageVersion = JavaLanguageVersion.of(21) } }references/maven-deps.md — Maven <dependency> blocks, BOM import scope, JDK toolchain notes.references/java-entry-points.md — every Java-friendly entry point currently shipped (SKaiNET, TensorJavaOps, StableHloConverterFactory, TokenizerFactory, TensorSpecs).~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.