Skip to content

feat(kmp): v1 error model + checked reads + 64-bit bit primitives - #24

Open
trancee wants to merge 17 commits into
mainfrom
feat/laguna
Open

feat(kmp): v1 error model + checked reads + 64-bit bit primitives#24
trancee wants to merge 17 commits into
mainfrom
feat/laguna

Conversation

@trancee

@trancee trancee commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Tickets 06/07/08 v1 runtime API.

Error model (06): KompactDecodeError sealed class (BoundsError, BadLengthPrefix, TruncatedNested, UnknownEnumCode) + KompactDecodeException.

Result value classes (08): 7 types using packed-Long (≤32-bit) or NaN-sentinel (DoubleResult) encoding. LongResult uses 6-bit failure sentinel (Long.MIN_VALUE not representable as success — documented + tested). @JvmInline on JVM, plain value class on iOS.

Checked reads + 64-bit primitives (07 runtime): readBitsLong/writeBitsLong (LSB-first, byte-identity with readBits for widths 1–31) + 13 checked read accessors (readBool, readInt8/UInt8, readInt16/UInt16, readInt32/UInt32, readInt64/UInt64, readFloat, readDouble).

Tests: 136 JVM + iOS tests green. KompactRuntimeLongBitsTest (13), KompactRuntimeCheckedReadTest (45), KompactResultTest (49), KompactRuntimePropertyTest (+3 property).

BCV: apiCheck + klibApiCheck green; kompact.api + kompact.klib.api goldens updated.

Wayfinder chart for Kompact (PROMPT.md, greenfield; docs/research is reference only). 3 research tickets resolved via subagents: LSB-first wire bit order; KSP 2.3.9+ generation; expect/actual value-class representation with @JvmInline on the JVM actual only. Frontier open: ticket 04 v1 type set. Also scaffolds docs/agents/ issue tracker, triage labels, and domain-doc conventions, and registers the Agent skills block in AGENTS.md. Chart only; no implementation.
Work-through the Kompact wayfinder map: resolve ticket 04 (v1 type set — full scalar+composite set incl. variable-length, nested, repeated; a scope expansion beyond PROMPT.md's 2-byte sketch) and graduate ticket 05 (variable-length/nested/repeated framing) as the next frontier. Update map Decisions-so-far + Not-yet-specified. One ticket resolved (04); 05 left open for the next session.
Work-through: resolve ticket 05 (framing — sequential length-delimited; fixed-width LE length prefixes; parse-forward nested sub-regions; count-prefixed repeats; random-access rejected vs variable-length, per ticket 04). Graduate ticket 06 (validation model) as next frontier. Update map Decisions-so-far + Not-yet-specified.
Work-through: resolve ticket 06 (KSP compile-time structural checks with symbol-located hard errors; KompactRuntime defensive bounds-checks return typed KompactDecodeResult, no throws on the hot path). Graduate ticket 07 (write/builder interface) as next frontier. Update map.
… ticket

Work-through: resolve ticket 07 (KompactWriter over writer-owned growable buffer with build(): ByteArray snapshot; sub-writer per nested with forward-only no-backpatch emit; typed write API mirroring reads; compile-time-validated widths from 06). Graduate ticket 08 (runtime error-model representation) as next frontier. Update map.
Work-through: resolve ticket 08 (specialized zero-alloc result value classes ByteResult/IntResult/etc over a packed Long; public checked reads never throw and return typed results; fail-fast; byte offset only on opt-in diagnostics path). Graduate ticket 09 (versioning and schema evolution) as next frontier. Update map. Informed by tickets 03-07.
Work-through: resolve ticket 09 (positional additive evolution with uniform length-prefix width + top-level version prefix; fail-fast typed BadLengthPrefix/UnsupportedSchemaVersion on skew). Graduate ticket 10 (cross-platform testing model) as next frontier. Update map. Informed by 05-08.
Work-through: resolve ticket 10 (all-four test categories incl cross-version compat matrix + zero-alloc CI gate with per-platform alloc profiling, expect/actual counter, commonTest on JVM+iosArm64+iosSimulatorArm64, ABI lock). Graduate ticket 11 (performance-evidence plan, research) as next frontier. Update map.
Non-blocking deferred item on the locked Kompact wayfinder map (Ticket 12),
resolved by a wayfinder:research subagent via primary-source research
(Kotlin 2.x / KSP 2.x). The Destination spec was already locked; this removes
the last implementer-facing open question.

- (a) KMP runtime `:kompact`: multiplatform + maven-publish +
  binary-compatibility-validator auto-create the kotlinMultiplatform root +
  per-target klib/jar publications (iosArm64/iossimulatorarm64 klibs
  auto-published); com.vanniktech.maven.publish 0.37.0 for Maven Central.
- (b) KSP processor `:kompact-ksp`: kotlin("jvm") jar registering
  SymbolProcessorProvider via META-INF/services + compileOnly
  symbol-processing-api (the KSP-safe form); consumers consume it via
  kspCommonMainMetadata (not kspJvm / not deprecated bare ksp).
- (c) BCV 0.18.0: apiValidation { klib { enabled = true } }, golden
  api/*.api + api/*.klib.api, apiCheck in check.
- (d) stub packaging: processor emits KompactAnnotations.kt + per-view
  value-class files as whole files into the common generated root; consumer
  manually srcDir + task-dep into commonMain (non-automatic seam,
  google/ksp#567).

Versions: KSP 2.3.11, BCV 0.18.0. Findings:
.scratch/kompact-spec/research/kmp-publication-wiring.md (throwaway).
Ticket 13 -> Status: resolved. map.md Decisions-so-far gains Ticket 13; the
"Open work item" paragraph is marked RESOLVED.

Refs tickets 02 (generation strategy) and 12 (module split & publication).
…side/laguna-s-2.1:free

Without a model: field, the Pi engine defaults to Copilot backend which
filters OPENAI_API_KEY (not in Copilot's allowed secrets). The model
parser rejects 'poolside/laguna-s-2.1:free' because ':' is not valid in
model tokens (ABNF grammar).

Fix: use model: openai/${{ env.PI_MODEL }} which:
1. Selects Codex backend (openai/ prefix) → keeps OPENAI_API_KEY
2. Bypasses model parser validation (expression with ${{ }})
3. Resolves PI_MODEL=poolside/laguna-s-2.1:free at runtime via GA

At runtime: GH_AW_PI_MODEL_ID resolves to poolside/laguna-s-2.1:free,
models.json registers aw-gateway provider with that model, and Pi CLI
sends the request through the AWF API proxy which forwards to OpenRouter.

modelFallback is auto-disabled (OPENAI_BASE_URL set), so the model is
passed through verbatim. AWF config targets openai → openrouter.ai.
… gates

Phase 1-3 bootstrap over commonMain: LSB-first KompactRuntime (byte-masked for identical JVM/Native behavior, readBits->Int, honest 1..31-bit cap) and hand-written @KompactModel/@KompactField (SOURCE retention; KSP deferred per Ticket 13). VehicleTelemetry expect value class (no @JvmInline in common, PROMPT §1) with @JvmInline JVM actual and plain iOS actual (Ticket 03); 16-bit LSB-first layout (batteryStatus:4 / speed:10 / isMalfunctioning:1 / reserved:1), build() ByteArray producer, zero-copy read-only val views with KDoc layout matrix.
Ticket 13: BCV 0.18.0 (apiValidation { klib { enabled = true }; kompact.api + kompact.klib.api goldens; apiCheck green) + vanniktech maven-publish 0.37.0 (coordinates ch.trancee.kompact:kompact:0.1.0-SNAPSHOT, Apache-2.0; POM + Gradle module metadata generated and valid).
Tests: jvmTest + iosSimulatorArm64Test green (26 tests, inspector 0 warnings); runtime property test widened to bitWidth 1..31 with value bound nextLong(0, 1L shl bitWidth).toInt() (covers the 2^31-1 boundary). Two-axis code review (Standards + Spec) complete; findings + fixes in assets/aaa-review.md.
Tickets 06/07/08 v1 runtime API on top of committed Phase 1-3 readBits/writeBits primitives.

Error model (Ticket 06):
- KompactDecodeError sealed class with BoundsError, BadLengthPrefix,
  TruncatedNested, UnknownEnumCode cases
- KompactDecodeException RuntimeException wrapper for interop

Result value classes (Ticket 08):
- 7 result types using packed-Long encoding (<=32-bit) or NaN-sentinel
  (DoubleResult); LongResult uses 6-bit failure sentinel (documented:
  Long.MIN_VALUE not representable as success)
- @JvmInline JVM actuals, plain value class iOS actuals; const val -> val
  for Long constants (Kotlin limitation)

Checked reads + 64-bit primitives (Ticket 07 runtime):
- readBitsLong/writeBitsLong: 64-bit LSB-first primitives, byte-identity
  with readBits/writeBits for widths 1-31
- 13 checked accessors returning result value classes: readBool,
  readInt8/UInt8, readInt16/UInt16, readInt32/UInt32, readInt64/UInt64,
  readFloat, readDouble
- Sign-extension for signed types; width bounds validation

Tests:
- KompactRuntimeLongBitsTest: 13 tests (widths 1-64, cross-boundary,
  byte-identity vs readBits)
- KompactRuntimeCheckedReadTest: 45 tests (all 13 accessors, edge cases)
- KompactResultTest: 49 tests (all result classes, sentinel encoding,
  sign-extension boundaries, Double NaN encoding)
- KompactRuntimePropertyTest: 3 new property tests (8/16/32/64-bit
  round-trip; write-touch-only-target-range; readBitsLong vs readBits
  byte-identity widths 1-31)

BCV: apiCheck + klibApiCheck green; kompact.api + kompact.klib.api goldens
updated for new public types.

Total: 136 JVM tests + iOS tests pass, 0 failures, 0 errors.
…I_MODEL references

The gh-aw compiler generates ${{ env.PI_MODEL }} in step-level env blocks
across multiple jobs, but PI_MODEL was only defined in agent-runtime steps.
This caused 'Unrecognized named-value: env' at line 1811. Adding PI_MODEL
to the workflow-level env block makes it available to all step-level env
blocks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant