Commit Graph
17 Commits
Author SHA1 Message Date
Dario LipicarandClaude Opus 5 ff8c3003a4 fix(cdylib): typed scalars go through the codec, and the emitted codec checks signedness (#115)
* fix(cdylib): typed scalars go through the codec, and the codec checks signedness

The cdylib dispatch decoded composites with the generated codec but scalars with
a bare nlohmann accessor. Two silent conversions lived in that gap:

    echoUint(-1)   -> 18446744073709551615   (.get<uint64_t>() wraps)
    echoInt(3.7)   -> 3                      (.get<int64_t>() truncates)

The Rust provider rejects both. So a contract both providers share answered
differently depending on which one a consumer resolved to, and one of the two
answers was a sign flip on a nominal value.

The reason this was left in place was circular, and it was written in the source:
the leniency "is pinned by the conformance matrix (`hostile/int/fractional`
expects 3 from 3.7 on this provider)". Those cells exist to DOCUMENT the
divergence — their own `why` text says the strict behaviour is correct. The
expectations moved with this change.

TWO sites, because fixing one relocates the bug rather than closing it:

  * jsonArgToStd no longer special-cases int/uint/float64/bool/tstr — everything
    typed goes through Codec<T>. `any` still passes through, since it declares
    nothing to check against; bstr keeps its tagged-bytes decoder.

  * the EMITTED codec (this generator writes its own copy into <name>_types.h,
    separate from logos_codec.h) gated integers on `is_number()`, which admits
    floats AND negatives. Routing scalars into it without fixing it would have
    changed nothing. The integer specializations are now spelled out rather than
    driven from the scalar table, because a category check is not enough for them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore: bump logos-protocol to the signedness + sentinel fixes

logos-protocol c0df466 (#31):
  * Codec<T> checks integer signedness and range, so a negative can no longer
    wrap into an unsigned and a wide value can no longer truncate.
  * the pending-call sentinel is matched by shape rather than key presence, so
    a user map merely carrying that key no longer hangs the call.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 12:13:30 -03:00
Dario LipicarandClaude Opus 5 7fbdfe26ac chore: bump logos-protocol to the uint64 fixes (#114)
logos-protocol 8b8a358 (#30) — two places where a uint64 above int64max stopped
being itself:

  * the universal -> Qt EVENT bridge converted with QJsonDocument::fromJson +
    QJsonValue::toVariant instead of the canonical helper the method path uses,
    so uintEvent(2^64-1) arrived as 1.8446744073709552e+19 while the equivalent
    method return was exact. The same bridge also failed to decode canonical
    tagged bytes into a QByteArray.

  * the plain (tcp/tcp_ssl) wire had no unsigned alternative in RpcValue, so the
    same value wrapped to -1 — silently, and independently in each direction.

Retires M6 from the LIDL conformance matrix.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 07:35:04 -03:00
Dario LipicarandClaude Opus 5 2ac8e8fc17 chore: bump logos-protocol to the lp owner-thread fix (#28) (#110)
Picks up logos-protocol ae2f7e1: lp clients on a Qt-affine transport are
constructed on the Qt main thread rather than on whichever thread makes the
module's first outbound call, which previously left the QtRO node and socket on
a thread with no event loop (every replica acquire then burned its full 20s
timeout and returned an empty result).

Hygiene only for this repo: `LpClient::ensure()` here already creates the client
lazily and that stays as it is — the fix is entirely inside the protocol's
lp_client_create. Module builds take their protocol from logos-module-builder's
`follows`, so they do not depend on this pin; this keeps cpp-sdk's own lock and
its tests on the same protocol as the rest of the stack.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 08:59:01 -03:00
Dario LipicarandClaude Opus 4.8 2e31eeb1ac chore: bump logos-protocol to the owner-thread destroy fix (#109)
Picks up logos-protocol#27 (8ede8ec), which stops lp_client_destroy from
deleting the LogosAPIClient on whatever thread released the last handle
share. Destroying it off the owner thread tore the QtRO transport's socket
notifiers down cross-thread and took the module process out with SIGSEGV;
the destroy now defers to the owner via deleteLater(). Reproduced and fixed
end-to-end under logoscore, 3/3 each way, with a control arm isolating that
commit as the cause.

This bump also crosses protocol#20 (group-shareable local sockets,
stale-socket reaper, bind-failure detection) — this repo's pin was one
release behind the other SDKs.

Checks green: logos-cpp-sdk-tests.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 20:19:01 -03:00
Dario LipicarandClaude Opus 4.8 f3de5527e2 chore: bump logos-protocol to master (rejection token re-exchange #26) (#108)
Picks up logos-protocol#26 (ef24bd7): provider returns the structured
unauthorized sentinel on a stale token; consumer drops it, re-runs
requestModule and retries once. Standalone `nix flake check`: 168/168 pass.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 18:28:26 -03:00
Dario Lipicar c3fa1b5ad3 chore: re-pin logos-protocol to master (LogosAPIConsumer handle cache) (#106)
Picks up logos-co/logos-protocol#24 (664b43f): LogosAPIConsumer caches the
remote-object handle per name across sync + async calls, avoiding a per-call
QtRO replica acquire. Consumer-side, ABI-compatible (appended virtual/member,
C ABI untouched).
2026-07-20 09:09:14 -03:00
Dario Lipicar ad30010f80 chore: bump logos-protocol to master (nested-bytes qvariantToNlohmann fix #23) (#104) 2026-07-17 20:13:51 -03:00
Dario LipicarandClaude Opus 4.8 d12a7bbb45 chore: bump logos-protocol to include plaintext-args log fix (#98)
Picks up logos-protocol 976bc7a (logos-co/logos-protocol#10), which stops
ModuleProxy::callRemoteMethod from logging call arguments in plaintext.
d5d58e7 (current pin) is the exact parent, so this is a one-commit bump.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 15:33:06 -03:00
Khushboo-dev-cpp 350a2891e6 chore: bump logos-protocol (#97) 2026-06-26 18:51:40 +02:00
Khushboo-dev-cpp 31b9d2bf5f chore: bump logos-protocol (#95) 2026-06-24 11:15:03 +02:00
Dario LipicarandClaude Opus 4.8 aea29d3797 Per-module concurrent dispatch: C++ module async export (#93)
* feat: emit logos_module_dispatch_async for concurrency:multi C++ modules

The cdylib C-ABI exports gain an async dispatch entry (each call run on a worker
thread, reply on completion) for universal + cdylib C++ modules. --concurrency
multi flag in logos-cpp-generator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: cpp-sdk concurrent-dispatch doctest (concurrency:"multi" showcase)

A concurrency:multi C++ worker + a single driver firing concurrent calls, showing
the multi worker overlaps them. The C++ cdylib generator needs NO change — its
logos_module_dispatch is already safe to call concurrently; the worker pool lives
in the Qt glue and the result is deferred via a sentinel + completion event.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: wire universal-cdylib modules() independent of the context latch

A C++ interface:"universal" cdylib that calls another module via
modules().<dep>... segfaulted on its FIRST cross-module call: the typed
dependency surface (LogosModules) was wired inside lidlTryFireContext, which
returns early when no persistence context was stored (g_ctxStored == false).
When the daemon never delivers a context (observed: zero set_context calls for
a context-less module), maybeSetLogosModules never ran, m_logosModulesPtr
stayed null, and LogosModuleContext::modules() dereferenced null.

modules() does not need the context — each dependency client bakes its
target+origin at codegen time and creates its lp client lazily on first call.
So wire it in its own context-independent once-latch (lidlEnsureModulesWired),
called at the top of lidlTryFireContext before the context-gated early return,
i.e. on the first dispatch / set_context / set_emit_callback. A module with
deps but no stored context now has modules() wired before any handler runs.
(Bump the concurrent-dispatch doctest's post-daemon-start sleep 3 -> 6 to match
the rust spec's cold-start margin.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: green the universal-cdylib concurrent-dispatch doctest + wire into CI

The driver/worker split a declarations-only impl header (so the cpp-generator's
--header-to-lidl doesn't choke on inline std calls) from the impl body. That
body was never compiled — metadata's nix.cmake.extra_sources is parsed but not
consumed by the LogosModule.cmake the build actually uses — so the impl symbols
(FanoutDriverModuleImpl::fanOut / ::peak) were UNDEFINED in the dylib and the
plugin null-jumped (bl -> 0x0) on the first cross-module call. Pass the impl
.cpp via logos_module()'s existing SOURCES argument so it's compiled and linked.

With this the cpp universal-cdylib reaches worker peak overlap 4 end-to-end (a
single-threaded driver fans out 4 async calls into a concurrency:"multi" worker
and all four overlap), matching the Rust half. Wire the spec into doctests.yml
so the workspace pipeline runs it.

(Auto-wiring metadata.extra_sources — so the split pattern works without listing
SOURCES by hand — needs the consumer added to the backend LogosModule.cmake
copies in logos-plugin-core / logos-plugin-qt; tracked separately.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump logos-protocol to merged master (protocol#5)

  logos-protocol  9de4165 → 4ea32a3  (concurrent-dispatch handshake coalescing, now on master)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 16:31:45 -03:00
Dario LipicarandClaude Opus 4.8 1bc101df1f feat: cpp-generator consumes logos-lidl; delete embedded frontend (#89)
* feat: cpp-generator consumes logos-lidl; delete embedded frontend

The canonical LIDL frontend now lives in logos-lidl. cpp-generator links it
and keeps only the C++/Qt-specific parts (impl-header parsing, the gen_client/
gen_cdylib backends, the Qt type-name mapping).

- Delete the embedded lidl_lexer/parser/serializer/validator/ast.
- Add experimental/lidl_compat.h: brings logos-lidl's std AST into the global
  scope the backends use (via `using`), a qs() std::string→QString helper, a
  QTextStream<<std::string overload, and name-compatible shims (lidlParse/
  lidlSerialize/lidlValidate) so the emission code keeps compiling.
- Re-point impl_header_parser, lidl_gen_client (+ Doxygen /// docs on the
  generated client methods), lidl_gen_cdylib, lidl_emit_common, and legacy/
  main at lidl::ModuleDecl.
- CMake: C++17 + find_package(logos-lidl) + link logos-lidl::logos_lidl.
- bin.nix: distribute only the shared C++/Qt backend helpers (compat +
  impl_header_parser + emit_common) under share/lidl-frontend, not the frontend.
- tests: drop the 4 frontend test files (covered by logos-lidl now); the
  backend tests link logos-lidl.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: pin logos-lidl to the C-ABI commit + lock it

The logos-lidl input was declared in flake.nix but missing from flake.lock,
so override chains that don't reach the nested input (the doctest harness
building a scaffolded module) couldn't resolve it. Pin the branch rev and
lock it so the component is self-contained. Re-point at master once logos-lidl
lands.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: re-point logos-lidl to merged master (#5)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 21:00:42 -03:00
Dario LipicarandClaude Opus 4.8 f0fe8cbfeb Make the base SDK Qt-free: Qt developer layer moves to logos-qt-sdk (#83)
* Extract the protocol layer into logos-protocol; consume it as a flake input

The transport/token/IPC layer (transports incl. QRO + plain TCP/TLS,
consumer core LogosAPIClient/LogosAPIConsumer with the capability
auto-requestModule flow, ModuleProxy, token manager, QVariant<->JSON
conversion, the abstract LogosProviderObject interface) now lives in the
logos-protocol repo behind the versioned lp_* C ABI.

This SDK keeps the typed C++ developer layer (LogosAPI, provider base
classes + Qt provider glue, module context, code generator) and still
compiles the protocol sources INTO liblogos_sdk.a from the flake input,
so the installed artifact (archive symbols, include/ + include/cpp
layouts, cmake config) stays byte-compatible: existing consumers need
no changes. Public headers are unchanged; logos_provider_object.h keeps
its name and now re-exports the abstract interface from
logos_provider_interface.h.

Transport/protocol component tests moved to logos-protocol with the
code; the remaining sdk/generator/experimental suites are unchanged
(432/432 green against the local protocol checkout).

* lock: add logos-protocol input

* Make the base SDK Qt-free: move the Qt developer layer to logos-qt-sdk

LogosAPI, LogosAPIProvider, LogosProviderBase/LOGOS_PROVIDER macros, the
QObject provider glue (QtProviderObject) and the legacy PluginInterface
(core/interface.h) move to the new logos-qt-sdk repo. The protocol
sources are no longer compiled into a monolithic archive — consumers
link logos-qt-sdk (which layers on logos-protocol) instead.

What remains here is header-only std C++: logos_module_context.h,
logos_result.h (StdLogosResult), logos_json.h — exported as the CMake
INTERFACE target logos-cpp-sdk::logos_headers — plus the code generator
(a build-time tool; its introspection mode now includes
logos_provider_interface.h from logos-protocol, where
LogosProviderPlugin moved).

Mechanically verified Qt-free: the logos-cpp-lib / logos-cpp-include
closures contain only nlohmann_json. Tests: 245/245 (module-context std
suite + generator + experimental).

* fix: accept the installed source-export layout in the protocol-root check

The fail-fast only tested <root>/cpp/logos_protocol.h, but the LP_SRC
selection right below (and the error message itself) support the
installed export layout <root>/include/cpp as well. Pointing
LOGOS_PROTOCOL_ROOT at an installed export tripped the FATAL_ERROR
before that fallback could apply.

Caught by Copilot review on #82.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* lock: pin logos-protocol to the qt-free-split branch head

The Qt-free SDK (and the cdylib backend stacked on it) reference
LogosProviderPlugin from protocol's logos_provider_interface.h, which
lands on feat/qt-free-split — the P1-branch pin no longer compiles
standalone. Temporary — drop when the chain PRs merge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* doctest: pin the logoscore runtime via its {release} placeholder

The spec built logoscore-cli at bare master with only the cpp-sdk inputs
overridden — master's stack cannot compile against the qt-free SDK, so
the suite failed on the chain branches. With the placeholder, CI's
--release-for pins expand it to the workspace's logoscore commit (and
local runs without a pin still fall back to master, unchanged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* doctest: override the nested module builders to {release} too

capability_module (via logoscore's lock) and the cloned accounts module
resolve module-builder from their own locks — pre-split revs whose
LogosModule.cmake still detects the SDK by logos_api.h, which the
qt-free SDK no longer ships ('logos-cpp-sdk not found'). Overriding the
builder itself to the workspace-pinned chain rev (keeping the nested
cpp-sdk override) builds both modules with the split-aware builder.
Verified end-to-end locally with the exact doctest command.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* doctest: apply the {release} + nested-builder overrides to all three specs

The runtime spec got the treatment in 210eea1; the composition and
worker-thread specs have the same logoscore/module build commands and
failed identically (pre-split builders from the modules' own locks).
All executed run: blocks now pin logoscore-cli{release} and override
the nested module builders to logos-module-builder{release}; the
displayed code_block: variants stay in their generic master form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* codegen: typed wrappers throw on call failure; dispatch catches escapes

Generated sync client wrappers call the new err-out invokeRemoteMethod
overload and throw logos::LogosCallError when the call fails (e.g. the
bound module is missing) — previously the empty QVariant silently
degraded to the return type's default and a caller could not tell
failure from a legitimate 0 / "". Both generators (legacy + LIDL),
both API styles. Async paths unchanged.

Generated provider dispatch (universal qt glue + LOGOS_PROVIDER) wraps
the method body in a catch-all that logs and returns an invalid QVariant
— an escaped exception becomes an ordinary METHOD_FAILED instead of
unwinding through Qt event dispatch and killing the module process.

* codegen: CallError out-param instead of throwing wrappers

Per review, the generated sync wrappers expose the error channel as an
optional trailing parameter — add(a, b, &err) — rather than throwing:
explicit, stateless, works on temporaries, and existing call sites
compile unchanged (they keep default-on-failure, now with a qWarning so
failures are visible in the module log). The dispatch catch-all from the
previous commit stays: it contains author exceptions, it doesn't
introduce any.

* glue: fire onContextReady AFTER modules()/event wiring

The generated onInit set the context (which fires the impl's
onContextReady hook) before constructing the LogosModules aggregate and
wiring typed event emission — so an impl doing its documented one-time
setup there (typed dependency calls, event subscriptions) dereferenced
a null aggregate and crashed the module process (signal 11). Found by
the first module to subscribe to a dependency's typed event from
onContextReady. Context now goes last.

* ci: run workflows on stacked PRs + workflow_dispatch

Both workflows filtered pull_request to master-based PRs, so stacked PRs
(feat/qt-free-sdk -> feat/extract-logos-protocol, feat/cdylib-authoring
-> feat/qt-free-sdk) ran NO checks at all. Drop the base-branch filter
for pull_request and add workflow_dispatch for manual runs. Same fix as
logos-module-builder 232b8a2.

* lock: protocol at the typed-requestModule port (3de5398)

* ci: chain pins for the doc-tests (drop at merge)

In repo CI only cpp-sdk's {release} is the commit under test —
logoscore-cli and module-builder expanded to master, which doesn't link
against the chain SDK the specs override in ('Build the CLI with the SDK
override' failed on every run since the stacked-PR triggers were
enabled). Pin both to the extraction-chain heads; the workspace pipeline
is unaffected (it pins every repo itself).

* generator: distribute the LIDL frontend for external generators

First step of moving ALL Qt glue emission out of this repo into
logos-qt-sdk's logos-qt-generator (cpp-sdk's generator keeps only the
Qt-free outputs: std typed wrappers, logos_sdk umbrella, cdylib
impl-exports, LIDL derivation).

- Shared emit helpers (lidlToPascalCase, lidlTypeToQt, lidlTypeToStd,
  lidlIsStdConvertible) move to a new lidl_emit_common.{h,cpp} unit, used
  by both generators.
- The frontend set (AST, lexer, parser, serializer, validator,
  impl-header parser, emit-common) is installed under
  share/lidl-frontend/ — the qt generator compiles these sources in
  directly, so the two tools share one frontend without a binary ABI.

* lock: protocol#3 merged — pin advances to protocol master

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 19:56:19 -03:00
Dario LipicarandClaude Opus 4.8 38bc77e127 Consume logos-protocol: the transport/token/IPC layer moves behind the lp_* C ABI (#82)
* Extract the protocol layer into logos-protocol; consume it as a flake input

The transport/token/IPC layer (transports incl. QRO + plain TCP/TLS,
consumer core LogosAPIClient/LogosAPIConsumer with the capability
auto-requestModule flow, ModuleProxy, token manager, QVariant<->JSON
conversion, the abstract LogosProviderObject interface) now lives in the
logos-protocol repo behind the versioned lp_* C ABI.

This SDK keeps the typed C++ developer layer (LogosAPI, provider base
classes + Qt provider glue, module context, code generator) and still
compiles the protocol sources INTO liblogos_sdk.a from the flake input,
so the installed artifact (archive symbols, include/ + include/cpp
layouts, cmake config) stays byte-compatible: existing consumers need
no changes. Public headers are unchanged; logos_provider_object.h keeps
its name and now re-exports the abstract interface from
logos_provider_interface.h.

Transport/protocol component tests moved to logos-protocol with the
code; the remaining sdk/generator/experimental suites are unchanged
(432/432 green against the local protocol checkout).

* lock: add logos-protocol input

* fix: accept the installed source-export layout in the protocol-root check

The fail-fast only tested <root>/cpp/logos_protocol.h, but the LP_SRC
selection right below (and the error message itself) support the
installed export layout <root>/include/cpp as well. Pointing
LOGOS_PROTOCOL_ROOT at an installed export tripped the FATAL_ERROR
before that fallback could apply.

Caught by Copilot review on #82.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* lock: protocol at the typed-requestModule P1 port (1e4bc72)

* lock: protocol at master (protocol#2 merged)

The extraction is on protocol master now (29afbac); the temporary branch
pin is dropped.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 19:21:00 -03:00
Dario Lipicar 25c88f4d48 support non-local remote transports (#57)
* support non-local remote transports

* fix LogosResult

* allow getting client over specific transport

* fix ssl

* investiage ssl error

* pr comments

* allow transport set configuration on any module

* pr comments

* add docs

* pr comments

* propagate only non-qt dependencies

* restore ABI compatibility
2026-05-07 12:27:14 -03:00
Iuri Matias 4b66dac015 follow logos-nix for nix packages (#26) 2026-03-19 17:39:45 -04:00
Iuri Matias bb5498edef feat: add nix flake
feat: add nix flake

test
2025-10-02 16:42:25 -04:00