Skip to content

Feat/enhance data contracts#170

Merged
lxsaah merged 17 commits into
mainfrom
feat/enhance-data-contracts
Jul 9, 2026
Merged

Feat/enhance data contracts#170
lxsaah merged 17 commits into
mainfrom
feat/enhance-data-contracts

Conversation

@lxsaah

@lxsaah lxsaah commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Data contracts as first-class capabilities

Reshapes AimDB's capability traits (Simulatable, Observable, Linkable, Settable) so each unlocks exactly one registrar verb, tiered by deployment role (wire/prod vs. dev-only).

Breaking changes

  • Simulatable: simulate(config: &SimulationConfig, ...)simulate(params: &Self::Params, ...). SimulationConfig/SimulationParams removed in favor of SimProfile<P> + RandomWalkParams. No more runtime enabled gate — sim vs. real is a compile-time #[cfg].
  • Observable: drops ICON/format_log(); now numeric-projection only (Signal, SIGNAL, UNIT, signal()). Presentation moved to ObservableRegistrarExt::log(node_id).
  • Settable: moved behind a new settable feature (was unconditional).
  • migratable: no longer requires std (now alloc-only).

Added

  • SimulatableRegistrarExt::simulate(profile, rng) — installs a .source() emitting synthetic samples on a timer. make check-no-sim (new CI step) proves rand never reaches a production build.
  • ObservableRegistrarExt::observe() — feeds T::signal() into a new core RecordRegistrar::signal_gauge, surfaced as live last/min/max/mean on record.list/record.get.
  • LinkableRegistrarExt::linked_from(url)/linked_to(url) — one-line link wiring defaulted to T::from_bytes/to_bytes; plus #[derive(Linkable)] for JSON wire types.
  • SyncProducer<T: Settable>::set_value/try_set_value/set_value_at — construct-and-send by primitive value instead of a hand-built T.

Docs & examples

  • New design doc: docs/design/041-data-contracts-integration.md.
  • README rewritten: contract table with tiers, "receipts" section, updated connector/platform lists.
  • weather-mesh-demo and mqtt-connector-demo examples migrated to the new trait shapes.
  • Per-crate CHANGELOGs updated; version bumps for aimdb-core (1.2.0) and aimdb-sync (0.6.0).

Verification

  • New tests: aimdb-data-contracts/tests/linkable_derive.rs, aimdb-sync/tests/settable_integration.rs, plus unit tests for the reshaped traits.
  • make check-no-sim added to CI (.github/workflows/ci.yml).

lxsaah and others added 16 commits July 6, 2026 04:39
…ate() verb (design 041 §3.1)

Reshape Simulatable to the one-verb-per-contract model and make simulation a
compile-time fact, not a runtime flag:

- Trait: add `type Params`; `simulate(params, previous, rng, timestamp_ms)`.
  Delete `SimulationConfig` (incl. `enabled`) and `SimulationParams`; add
  `SimProfile<P>` + off-the-shelf `RandomWalkParams`.
- New `SimulatableRegistrarExt::simulate(profile, rng)` installs a source loop
  over `ctx.time()` (runtime-neutral, single-writer enforced by build()).
- Cargo: `simulatable = ["rand", "aimdb-core"]`; `rand` drops `std_rng`
  (caller-supplied RNG; SmallRng needs no feature).

D1 callers:
- weather-mesh-common temp/humidity/location impls → `type Params = RandomWalkParams`.
- weather-station-beta (std) + gamma (no_std): `sim` feature gates
  `.simulate()`; default (prod/flash) build reads a hardware source and is
  rand-free — the canonical §3.1.4 `#[cfg]` sim-to-real pattern.

CI: `make check-no-sim` proves each station's production graph carries no
`rand` (the tracer) and that `simulatable` is never a default feature; wired
into the CI makefile-build job.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Removed `ICON` and `format_log` from the `Observable` trait, simplifying the interface.
- Introduced `SignalGaugeHandle` for managing signal statistics, allowing for last/min/max/mean tracking.
- Added `SignalStats` struct to encapsulate signal statistics with atomic operations for thread safety.
- Updated `RecordProfilingMetrics` to include signal gauges and their statistics.
- Enhanced `RecordMetadata` to optionally include signal statistics when the observability feature is enabled.
- Modified `ObservableRegistrarExt` to support signal observation and logging.
- Updated various schemas (e.g., `Temperature`, `Humidity`, `DewPoint`, `GpsLocation`) to align with the new observability model.
- Adjusted example applications to utilize the new signal gauge functionality for metrics and logging.
…ign 041 §3.3)

Implementing `Linkable` today changed nothing — every example hand-wired
`with_deserializer`/`with_serializer` closures. Fix:

- `LinkableRegistrarExt::linked_from`/`linked_to` install `.link_from()`/
  `.link_to()` with the codec defaulted to `T::from_bytes`/`T::to_bytes`; the
  raw builders remain the escape hatch for per-link options (QoS, topic
  providers/resolvers).
- `linkable` feature now depends on `aimdb-core` (same wiring as `observable`)
  for the registrar/connector-builder types the ext needs.
- `#[derive(Linkable)]` in `aimdb-derive` emits `serde_json::to_vec`/
  `from_slice` — no_std + alloc compatible (serde_json here is alloc-only, no
  `std` required), removing hand-written JSON boilerplate.

D1 caller: tokio-mqtt-connector-demo's TempOutdoor/TempServerRoom (outbound)
and CommandKey::TempOutdoor (inbound) now use `#[derive(Linkable)]` +
`.linked_to`/`.linked_from`; TempIndoor keeps the raw builder since it needs
QoS/retain options the ext doesn't cover. mqtt-connector-demo-common gains an
opt-in `data-contracts` feature (alloc-only) so the embassy demo's hand-rolled
no_std JSON path stays untouched — it doesn't enable the new feature.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`Settable` was built for the sync bridge, but `aimdb-sync` never referenced
it — `SyncProducer::set(value: T)` takes a fully constructed record, so every
outside-the-thread caller hand-assembled the struct.

- `Settable` moves behind a `settable` feature in `aimdb-data-contracts` for
  tier symmetry with the other wire contracts (pure trait, no dependencies of
  its own). weather-mesh-common enables it unconditionally (used by all three
  contracts); codegen's `generate_cargo_toml`/import emission gained the same
  `has_settable` detection already used for `has_observable`.
- `aimdb-sync` gains a `data-contracts` feature -> optional
  `aimdb-data-contracts/settable` dep (dependency direction stays
  contracts -> sync, no `sync` feature added to the contracts crate).
  `SyncProducer<T: Settable>::set_value`/`try_set_value`/`set_value_at`
  construct via `T::set(value, timestamp)` and send; `set_value`/
  `try_set_value` stamp the caller's `SystemTime`, `set_value_at` takes an
  explicit timestamp for replay/testing.
- Doctest + integration tests (aimdb-sync/tests/settable_integration.rs)
  exercise `set_value`/`try_set_value`/`set_value_at` end-to-end
  (construct -> produce -> consume).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…n 041 §6-7)

- README: the 4-trait capability table becomes the §2 verb/tier table
  (Contract / Implement when / Verb / Tier), documents the `Simulatable`
  dev-tier "never ships in prod" call-out with the `#[cfg]` sim-to-real
  pattern, and adds the `Settable` row.
- CHANGELOG entries for all four touched crates (aimdb-data-contracts,
  aimdb-core, aimdb-derive, aimdb-sync) describing the trait reshapes, new
  registrar ext traits, the signal-gauge surface, and the derive macro.
- Version bumps: aimdb-data-contracts 0.2.0 -> 0.3.0 (breaking: Simulatable/
  Observable reshaped, Settable feature-gated), aimdb-core 1.1.0 -> 1.2.0
  (additive: signal_gauge surface), aimdb-derive 0.2.0 -> 0.3.0 (additive:
  #[derive(Linkable)]), aimdb-sync 0.5.0 -> 0.6.0 (additive: set_value
  family). Dependents pinning an exact version (aimdb-sync, aimdb-wasm-
  adapter, aimdb-websocket-connector -> data-contracts; aimdb-core,
  aimdb-data-contracts -> aimdb-derive) updated to match; aimdb-core's own
  0.x-style dependents needed no change (^1.1.0 already permits 1.2.0).

Verified: `make check` and `make build` green in aimdb; `make check`/`make
all` green in aimdb-pro against the bumped versions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(review): SignalStatsInfo serde symmetry, live hub gauge, gamma fmt

Review follow-ups on the design 041 implementation:

- SignalStatsInfo.unit: add #[serde(default)] to match its
  skip_serializing_if. Observable::UNIT defaults to "", so a gauge
  without a unit serialized record.list/record.get JSON that
  aimdb-client/aimdb-mcp (built with observability) could not
  deserialize back (missing field `unit`). Regression test added.
- weather-hub: enable aimdb-tokio-adapter/observability so .observe()
  gets a live gauge instead of the inert handle — the demo now actually
  surfaces signal stats on record.list/record.get as its comments and
  design 041 §6 claim.
- weather-station-gamma: rustfmt the non-sim read_temperature signature
  (make fmt-check was failing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017sJzkN61UVQboWuHVHwSKP

* ci: make check-no-sim fail closed + tracer positive control

The guard treated ANY non-zero 'cargo tree -i rand' exit as 'rand is
absent'. An unrelated cargo failure — missing _external submodules, a
typo'd package in SIM_EXAMPLES, registry trouble — therefore passed the
check vacuously (observed: with submodules uninitialized, all four
assertions 'passed' while cargo was erroring on embassy-executor).

Now 'rand-free' is accepted only when cargo tree fails with its specific
'did not match any packages' error; any other failure aborts the check
and prints cargo's output. A positive control per example additionally
asserts the '--features sim' graph DOES find rand, so a silently broken
tracer (e.g. rand dropped from the simulatable feature) can no longer
turn the whole guard into a no-op.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017sJzkN61UVQboWuHVHwSKP

---------

Co-authored-by: Claude <noreply@anthropic.com>
- Updated comments in `linkable.rs`, `observable.rs`, and `simulatable.rs` to improve clarity and remove references to design documents.
- Enhanced documentation in `lib.rs` of `aimdb-derive` to clarify the derive functionality for `Linkable`.
- Revised comments in `Cargo.toml` files across various examples to remove design references and improve readability.
- Adjusted comments in `producer.rs` and integration tests to clarify the functionality of `SyncProducer` and its methods.
- Updated design documentation to reflect changes in the implementation and clarify the purpose of various traits and features.
- Removed unnecessary design references in example projects to streamline the documentation and focus on functionality.
@lxsaah lxsaah marked this pull request as ready for review July 9, 2026 17:04
@lxsaah lxsaah merged commit b4e0ce0 into main Jul 9, 2026
8 checks passed
@lxsaah lxsaah deleted the feat/enhance-data-contracts branch July 9, 2026 18:22
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