Logoscore Weekly Update — 2026-09-21
Highlights
- The blockchain node’s dashboard was rebuilt around what an operator can act on. The status hero’s eleven states became six — replay folds into Bootstrapping,
Stopped/Not connectedinto Not started — and progress now comes from the node’s pushedprocessedBlockstream rather than the status poll alone, so an arriving block vetoes the stale treatment and collapses the poll backoff instead of a busy-but-healthy node being reported as broken. Diagnosis ranks root cause over consequence, and names a chainsync protocol mismatch rather than blaming unreachable peers, which is the symptom it produces. Around the hero: peers, slot, height, LIB, tip and epoch as tiles that each carry an ⓘ explaining what the number means, plus chain ID, CPU, memory, disk, uptime, stake notes and the value a claimable voucher actually holds logos-blockchain-ui#65, #66, #68, #70, #71 - A provider swapped faster than the one-second liveness poll was invisible, and its replacement’s events arrived on the old subscription under the old generation. Detection is event-driven now: every loss goes through
setState(Suspect), which QtRO emits synchronously on every configured facade, so a handle that saw its source depart stops passing events even after QtRO re-validates the facade. Measured withlogoscore reload-moduleover 20 swaps: 10/20 silent on macOS and 15/20 on Linux before, 0/20 after, withLOSTreported ~50 ms after the old process’s last event. The same PR fixed a second bug its control test exposed — the generation counted subscribers, so five subscribe/cancel cycles on a healthy module took it from 1 to 6, which two consumers read as restarts logos-protocol#91 - Mining and claiming moved into the UI, because mining is how a fresh node funds its own stake. PoW rewards are paid into the leader’s funding key, which is what PoS stakes from. A wizard screen configures the knobs and claim period and picks auto-claim targets from the accounts the config already tracks, with the leader funding key listed first and marked — it is the only choice that turns mined rewards into stake — and Confirm writes the whole section in one
powConfigure, so a rejected target cannot discard the settings beside it. The Mining tab’s counts exist because auto-claim runs unattended and reports failures to the node log, which the app cannot read: a claimable count that climbs while nothing is ever claimed raises a warning on the card. Claims are counted from blocks, since the claim op is the only place a settled reward is visible —pow_claimable_rewardsreports tickets waiting, not ones paid. Tickets-in-flight defaults to 2, not the node’s 4: each claim carries a proof and the batch must fit one Blend payload, which 4 overruns, so every claim is rejected and the tickets expire unclaimed logos-blockchain-ui#67 - A module now ships its own contract and answers for it.
lidl() -> tstris reserved as a built-in alongsidename()andversion(), generated by every SDK, and the canonical document is installed into the package atassets/lidl/— platform-independent root assets in the LGX format, extractable without unpacking a variant, which is what the bridge’s offline docs renderer and the Python code generator were waiting on. Two defects fell out of doing it properly: the Qt glue answeredlidl("junk")withnulland status ok while every other zero-parameter call was refused, and legacy-> voidcontracts are now normalised to an absent return clause rather than a sentinel type logos-lidl#12, #13, #14, logos-module-builder#247, logos-package#40, #42, logos-plugin-qt#42 - Every amount in the app had been the node’s raw lepta count, because the node publishes no denomination and so nothing scaled it. Amounts now render in LOGOS (1 LOGOS = 10⁹ lepta, symbol LGO) with lepta kept as the wire format, so no hop loses digits. The formatting slices strings rather than going through
Number(): a lepta figure runs past 2⁵³ — the faucet note isu64::MAX— andNoteSelectorhad been summing note values that way, reporting a silently wrong total. Nothing is rounded and trailing zeros are trimmed, so one lepta reads0.000000001 LGOrather than a0.00that claims the balance is empty; only the locale’s own separator counts as the decimal point, since accepting.as well would make1.5mean 15 to adeuser logos-blockchain-ui#69 - A use-after-free dating to June was crashing the JSON-RPC bridge.
requestObject()’s timeout branch deleted the facade it had just waited on — and awaitForSourcetimeout means precisely that the class definition never arrived, which is when the sharedQConnectedReplicaImplementationstill holds that facade as a raw pointer inm_parentsNeedingConnect;~QRemoteObjectReplicais an empty body that never deregisters. The module’s next source publication walked that list into freed memory: SIGSEGV inQMetaObjectPrivate::connect. It needs a second live facade for the same name to be reachable at all, which is why it hit the bridge and not simpler consumers. The timed-out facade is parked and handed to the next waiter instead — parking alone would be unbounded — and the two crash cases are validated on the pre-fix tree: SIGSEGV 5/5 runs before, 602/602 green after logos-protocol#95 - Accounts, Transfer and Channel Deposit became one Wallet section picked between by a left menu, with Rewards, Mining and Wallet gated on a running node so a dead node cannot be asked questions it has no answers to logos-blockchain-ui#72 — and the three controls that dashboard is built from landed in the design system:
LogosStatCard,LogosStageLaneandLogosInfoButton, plus avalueColorthat tints a value without claiming a severity.severitydid three things at once, so a value worth colouring but not worth flagging had to claim one and got an icon with nothing to say — for Info that icon is an ⓘ, indistinguishable from the info button beside it logos-design-system#56, #57, #58, #60, #61 - A catalog can now draw packages from other catalogs. An
includesUrlon the identity card points at a document listing the catalogs it draws from — whole catalog, named packages, or pinned versions — resolved at fetch time, so a composed catalog stays current without republishing and an included version keeps theurl,rootHashandsignatureits origin published. Nothing is re-hosted. A drawn-in row is deliberately stamped with the configured repository’s url, because the listings group on that field and hide an empty section, so origin-stamping would render an aggregate catalog as nothing at all — which is why provenance travels separately and the Details panel is the surface that saysRepository: My Distro (drawn from Team B)logos-modules-release-tool#8, logos-package-downloader#40, logos-package-manager-ui#83, logos-logoscore-cli#139 - The plain TCP transport never reported a provider restart at all, and never recovered from one.
PlainLogosObjectinheritedisValid() == truefrom a connection that was closed for good, so the watchdog had nothing to see, and nothing redialled because no production code callsreconnect(). It now reports loss through the same registry path as qt_remote and redials in the background on a bounded 5 s dial; the first connect adopts that same dial, so a peer that accepts TCP and never answers the handshake no longer hangs a consumer’s constructor for good; and a call made on the shared io thread starts the redial and fails at once rather than waiting out a redial that can only run on the thread it is blocking logos-protocol#92, #93, #94 - A human was approving a fee no screen showed. The approval commitment covers a transaction’s fee fields and so does the signature, but
render_linesnever rendered them — a zero-tip transaction that sat unmined on mainnet for two days went through the signer looking like any other. Each leg now shows its max fee and priority fee in wei and gwei,Fee at mostin the native coin, and a** ZERO PRIORITY FEE — this may never be included **flag. Underneath, a failedeth_feeHistoryhad been swallowed into an empty history, which reads as a chain with no base fee — so every tier came frometh_gasPricewithmaxPriorityFeePerGas: 0, and tx_sender, which signs only type-2 transactions, turned that into a real zero-tip transaction logos-evm-keystore-module#21, logos-evm-fee-module#8 - RLN stopped being something a client configures. A node’s RLN comes from the network preset its
createNodeconfig already carries, withrlnStateandrlnStateChangedreportingDisabled/Initializing/Ready/Failedso a caller can read the same deployment back without keeping a second copy of the table. Every shipped preset has RLN off, which is what the networks page already documented, so no node’s behaviour changed — and the module is an optional dependency now, so a node on such a preset runs without the RLN stack installed at all logos-delivery-module#118, #126, logos-delivery-demo#32 - One flake-input cycle was costing every bundler thousands of lock nodes.
modules-state-module → module-builder → standalone-app → liblogos → modules-state-modulecannot be expressed in a lock, so nix unrolls it and every consumer inherits the whole subtree once per path it reaches the module by. Onefollows = ""cut it: that module’s own lock 690 → 104, liblogos 880 → 294, Basecamp 3939 → 2767 and logosctl 16886 → 15714, with the bundled plugins byte-identical before and after logos-modules-state-module#5, logos-liblogos#221, logos-basecamp#425, logos-logoscore-cli#137, logos-standalone-app#57
Initiatives
Blockchain UI — a dashboard that explains itself
Eight PRs, from the status hero down to the unit every number is printed in.
- The hero, and where progress comes from. Eleven states to six; losing the poll greys the last known state rather than replacing it, so a busy-but-healthy node is no longer reported as broken.
processedBlockis subscribed rather than inferred — an arriving block vetoes the stale treatment and collapses the poll backoff — andget_time_infocame off the status path so polling can run at 2 s catching up and 12 s online with no give-up-and-ask-the-user pause. The header took the Logos mark and “Blockchain Node”,At Headslotwas dropped and Epoch added fromcurrent_epochlogos-blockchain-ui#65 - Liveness stopped being one probe deep. A single missed probe had been declaring a busy node dead; three consecutive misses are now required, and any arriving block clears the count, since a module pushing blocks is alive whatever the transport says. A stop pressed from Running had also been sharing the fifteen-minute deadline meant for a stop queued behind a replay, leaving the button dead and silent throughout logos-blockchain-ui#67
- Uptime, an asynchronous start, and a crash that is reported as one. The uptime clock is driven off the status reading and stopped by every path that leaves Running, so it cannot keep counting for a node that is gone; its tick tiers mirror the smallest unit the view renders. Start no longer blocks, and a module that dies during one is reported — a crashed node used to sit on “retrying in Ns” for good. Large figures shrink to fit rather than being abbreviated to K/M/B, which was hiding the digits an operator is checking logos-blockchain-ui#66
- Chain identity, and the resources the node is actually using.
get_chain_idis read once the node is Running and cleared on every transition out of it. CPU and memory come from the node process itself: the PID is resolved frommodules_state’sModuleRecord, and the first CPU sample of a PID is discarded rather than published as0, because it is a delta against a previous sample that does not exist. Disk is a directory walk over the chain db, sampled at 20 s — it touches every file the db holds, and disk moves slowly enough that a 20-second figure is never misleading. A missingmodules_statecosts those two tiles and nothing else logos-blockchain-ui#71 - Stake, shaped by the backend. Total, note count and addresses from
wallet_get_leader_aged_notes. A transient failure keeps the last figure, because it is still true; going offline clears it, because leaving it up would assert a stake the node no longer has. An empty total means “not reported” and a reported0means nothing has aged — two different answers that had rendered identically logos-blockchain-ui#68 - Every tile got an ⓘ that says what its number means — peers, slot, height, LIB, tip, epoch, Blend — with the claimable-vouchers card now showing the value a voucher holds rather than just a count, and the stage lane completing all of its stages logos-blockchain-ui#70, #71
- LGO, everywhere, with lepta kept on the wire. Scaling text back to lepta lives in
BlockchainBackend::leptaFromLgo, which owns the u64 bound and the error messages; QML only strips grouping and normalises the decimal point, and the field validator refuses the other separator so the ambiguous form cannot be typed logos-blockchain-ui#69 - One Wallet section — Accounts, Transfer and Channel Deposit behind a left menu, sharing one
SectionNavwith the rest of the app; Rewards, Mining and Wallet cannot be opened without a running node, which takes all three wallet panels with them logos-blockchain-ui#72 - The design-system side.
LogosStatCard,LogosStageLaneandLogosInfoButtonship with storybook pages and unit tests, plus a compact size and Danger variant onLogosButtonand aborderGlyphtoken; then the card gained states, an externally-filled info dialog,valueColor, and two caption fixes logos-design-system#56, #57, #58, #60, #61
Canonical LIDL — the contract travels with the module
- The identity method.
lidl() -> tstris reserved and injected alongsidename()andversion(), exposed through the C API and the canonical serializer, with canonical output stability tested rather than assumed logos-lidl#12 - Generated by every SDK, as a built-in that needs no trait code on the Rust side, with goldens and provider fixtures regenerated logos-cpp-sdk#162, logos-rust-sdk#61, logos-plugin-qt#38, logos-qt-sdk#56
- Bundled into the package. Contracts are normalised before code generation, so
#lidl, the generatedlidl()and the package asset are one document; a core module installs its own plus those of itsdependencies,interface_dependenciesandoptional_dependencies, UI plugins get dependency contracts only, identical copies are deduplicated and same-name conflicts refused. End to end,assets/lidl/minimal.lidlis byte-identical to the minimal module’s#lidloutput logos-module-builder#247, nix-bundle-lgx#15, nix-bundle-logos-module-install#8, logos-tutorial#91 - Platform-independent root assets in the LGX format, preserved across a merge, with paths and conflicts validated — and extractable on their own, since a program that only wants a contract had to unpack a whole variant, binaries included, to get one. Two are waiting on it: the bridge’s offline docs renderer and the Python code generator logos-package#40, #42
lidl("junk")answerednullwith status ok. The Qt glue answers the generator-ownedlidl()itself, beforelogos_module_dispatchruns, and its own argument check returned an emptyQVariant— whilename("junk"),version("junk")and every contract method with the wrong arity were refused. The providers were never the problem: calling dispatch directly on each plugin already answeredinvalid_args. Conformance cells landed green on the relock logos-plugin-qt#42, logos-module-builder#252, logos-test-modules#64, #63- No-return methods are now structural — an absent return clause, serialized as
method notify(), with historical-> voidaccepted only to migrate it away, sonilstays available for its CDDL null meaning instead of doubling as an absence marker. Carried through all four generators and the builder’s legacy contracts logos-lidl#13, logos-cpp-sdk#163, logos-rust-sdk#62, logos-plugin-qt#40, logos-qt-sdk#57, logos-module-builder#249 - A
lidlcommand-line tool —json,check,fmt, with typed exit codes — so scripts and other languages reach the canonical parser, identity pass, validator and serializer without linking the C ABI; the bridge’s Python SDK uses it and its CI checks that readers handle what writers produce. Measured:lidl fmtreturns 134 of the 138.lidlcontracts in the local store byte-for-byte, and the other four differ only in their legacy-> voidlines logos-lidl#14 - Multi-dispatch became a bounded pool. One QThread per call was exhausting process descriptors under a request burst (
QThreadPipe: Unable to create pipe: Too many open files, on macOS); a reusableQThreadPoolwith an optionalmax_workersin metadata replaces it, CPU-sized when omitted, with explicitly capped workers pre-created before networking load can exhaust the pipes logos-plugin-qt#39, logos-module-builder#248, logos-tutorial#92
The protocol — restarts you can see, and a replica that must not be freed
- Why polling could not see a fast swap, and an event can. QtRO re-attaches the same replica facade to the replacement source, so by the next poll the handle is valid again and its event helper is already receiving the new process. Every loss, though, goes through
setState(Suspect), which is emitted synchronously on every configured facade — so a bound handle stops passing user events at the loss and cannot be revived under the old generation whatever order the event loop runs things in logos-protocol#91 - The generation now counts establishments, not subscribers. The header tells
lp_subscribecallers to detect gaps by watching it, and two consumers act on it today, so five subscribe/cancel cycles on a healthy module reading as five restarts was a live defect, not cosmetics logos-protocol#91 - Plain transport, three PRs deep. Detection (a failed plain connection never reopens, so
isValid()can report it and the existing 1 s poll suffices), a bounded background redial, the first connect bound by that same dial with a 5.5 s cap because a busy io thread cannot fire its own deadline, and finally the io-thread case: a call from an event handler that waits on a redial is waiting on work that can only run on the thread it is blocking logos-protocol#92, #93, #94 - Parked, not deleted. The timed-out facade is parented to
m_pendingAcquires, which both the destructor andreconnect()destroy before the node, so it can never outlive the implementation pointing at it;takeParked()hands it to the next waiter, bounding the count by concurrent waiters rather than by retries.Uninitializedis the test, because for a dynamic replica that state means exactly “the implementation has no metaobject yet”, which is exactly when it holds the facade raw logos-protocol#95 - Two propagation waves, seven steps each, because a module plugin carries its own static copy of the transport: cpp-sdk and plugin-qt, then qt-sdk and view-module-runtime, then module-loader-qt and test-framework, then liblogos, the standalone app, module-builder — the step that puts the fix into every module built with it — and finally Basecamp and logosctl. Neither carried a MINOR bump, so plugin-qt’s consumer-admission bound stayed put logos-cpp-sdk#164, #165, logos-plugin-qt#44, #45, logos-qt-sdk#58, #59, logos-view-module-runtime#34, #35, logos-module-loader-qt#17, #18, logos-test-framework#10, #11, logos-liblogos#216, #218, logos-standalone-app#53, #54, logos-module-builder#255, #256, logos-basecamp#422, #424, logos-logoscore-cli#135, #136, logos-test-modules#65
- And a second liblogos relock for the modules it bundles, since
capability_moduleandmodules_statelink the transport statically from whichever builder their repos pin — measured in the shippedliblogos-bin: the dylib exportedtakeParked, neither bundled plugin did logos-capability-module#31, logos-modules-state-module#4, logos-liblogos#220, logos-standalone-app#55
Catalogs that draw from other catalogs
- The format half.
includesUrlis reached from the identity card, never fromindex.json— the index is regenerated wholesale on every publish and on a 6-hourly cron, so a hand-authored entry there is destroyed on the next rebuild. The card points rather than carries, the same splitindexUrlalready makes, and both hand-edited files got a validator logos-modules-release-tool#8 - The client half. Resolution at fetch time, folded into the including repository’s listing, with ranges going through the existing
semverRangeMatchesso the dialect cannot drift from the resolver’s. Provenance rides in neworigin*fields on the entry and on every version entry, because after a merge one package’s versions can come from several catalogs logos-package-downloader#40, logos-package-downloader-module#39 - Rendered in both frontends, and in the CLI. The Details panel follows the version picker, so it cannot keep naming whoever published
versions[0]while showing another catalog’s version and hash beside it, and falls back to the configured repository when the origin is absent or empty.catalog lsprints the declaredincludesUrlwith the resolved catalogs nested under it — including one that resolved to nothing, since a catalog whose includes document is unreachable must not read as one that never meant to draw from anybody logos-package-manager-ui#83, logos-logoscore-cli#139, #140, logos-basecamp#428 - Two PMUI fixes rode along. A locally-installed package reported
Dependencies: Nonehowever many its manifest declared — the synthetic “Local” row hardcoded the field, and for a package outside every catalog that row is the only surface there is; and the version cell now tooltips what it elides logos-package-manager-ui#82, #80
EVM — fees on the screen that signs them, and a router for any pair
- A bundle priced as the chain will find it.
estimate_bundleprices calls leaving in order from one account: an ERC-20approvein an earlier call becomes aneth_estimateGasstate override on that token’s allowance slot for every later one, so a swap behind its approval gets a real estimate instead ofexecution reverted: STF. The slot is found rather than assumed — oneeth_callofallowance(owner, spender)carries 64 sentinels across the Solidity and Vyper layouts, and only the slot the token actually read is overridden (USDC: slot 10). Tiers moved to p10/p30/p60, because the top of a block’s reward distribution is MEV — p90 measured at ~1 gwei against a 0.07 gwei base fee logos-evm-fee-module#6 - A fee read that fails is an error, never a zero tip — and a fee field the caller sets alone is honoured rather than dropped without a word, which is what the wallet’s Advanced section produces when a user fills in only the priority fee logos-evm-fee-module#8, #9
- A complete quoter and encoder for any pair. V2 direct and via WETH, V3 direct on every fee tier and via WETH on every tier pair, all in one Multicall3 batch; a one-thousandth probe beside every route stands in for the marginal price, so the winner’s shortfall against it is
priceImpactBps; with anownerthe same batch reads balance and per-router allowance, so the reply says whether the swap is affordable and whether an approval must go first. V3 is encoded for SwapRouter02 and wrapped in itsmulticallwith the deadline — the legacy router has none, Sepolia has no legacy router at all, and Base’s seeded router already was SwapRouter02 but was being encoded for the legacy one logos-evm-uniswap-module#10 - Refusals relayed whole. A closed verified-proxy gate came back as its error text wrapped in a new object, losing
codeandverifiedProxy— the verdict and the action to offer — so a caller could not tell “the proxy is not running” from any other failure logos-evm-uniswap-module#12 - An EIP-712 typed-data leg, carrying the standard’s own JSON and computing the signing hash itself rather than trusting one from the requester, rendering domain, primary type and every message field with nesting indented under it. A document is refused when its message carries a field the declared type lacks — it would be shown but signed by nobody — when a declared field is missing, or when it contains a control character logos-evm-keystore-module#15
- A displaced approval stays approvable. The Signer shows one at a time, and acknowledging a newer one demoted the record on screen back to
Offeredwith itsoffered_atkept — so the abandoned-offer sweep expired it 60 s later, although a human had opened it. A record isclaimedonce acknowledged, and the sweep now collects only offers nobody came for logos-evm-keystore-module#19, #20 - Reads answered while a token list downloads.
refresh_nowdownloaded each list URL in turn on the module’s only call thread, so the wallet backend lost every token read for the duration and could prepare no send, native ones included. Declaredconcurrency: multiwith the store behind anRwLockheld only to read the plan and apply the result: measured against a 15 s list,list_offeredwent 14.2 s → 0.2 s, while the refresh itself still takes as long as its slowest list rather than their sum logos-evm-token-list-module#11, #8 - A reusable chain registry, each default chain offered once per device,
eth_feeHistory’s block count kept hex on the verified leg, and account wallet provenance exposed as one ungated read so the wallet backend composer stops recreating that join across module calls logos-evm-eth-rpc-module#14, #16, #17, logos-evm-keystore-module#16 - The stack versioned together — all 18 packages at 0.1.0 with every in-stack dependency at
~0.1.0, merged in three waves because the loader refuses an out-of-range dependency and the doctests build each dependency from its repo’smain. The specs now name today’s callers too, each one read from that module’sglue.rsandmetadata.jsonon its default branch rather than from other docs logos-evm-keystore-module#17, logos-evm-eth-rpc-module#15, logos-evm-token-list-module#9, logos-evm-fee-module#7, logos-evm-uniswap-module#11, logos-evm-signer-ui#17, logos-evm-eth-rpc-module#18, logos-evm-keystore-module#22, logos-evm-uniswap-module#13, logos-evm-signer-ui#18, logos-evm-net-proxy#4 - Hygiene around it: the signer took
logos-tx-decoder’s swap reading, and the modules caught their locks up to each other’s mains; the keystore’s two table tests stopped writing into the shared$TMPDIR, where they left encrypted vaults behind on a persistent runner and two concurrent runs collided outright; and the token-list README stopped telling callers to gateinit_defaultsonconfig_status, which only ever added a hop — it answersapplied: falseonce a list is configured, and it checks inside the same&mut selfcall that writes logos-evm-signer-ui#16, #19, #20, logos-evm-fee-module#10, logos-evm-uniswap-module#14, logos-evm-keystore-module#18, logos-evm-token-list-module#10
Delivery and RLN — the preset decides
configureRlnis not a module method any more. A preset → RLN settings table lives in the module,LOGOS_DELIVERY_RLN_PRESETSnames a JSON file merged over it for a deployment that is not one of the shipped presets, andcreateNodeinstalls the library’s RLN plugin synchronously before bringing the backend up on its own thread — because the library reads the plugin at node creation, so a later call would silently do nothing logos-delivery-module#118, #120- Optional, and therefore absent.
liblogos_rln_modulemoved tooptional_dependencies— a re-land, since the first attempt was reverted when module-builder 0.2.5 could not parse the key and 0.3.0 can. A node whose preset has RLN off, which is every shipped preset, now runs without the RLN stack installed logos-delivery-module#126, #122 - A message now says where it came from.
source(live/history) joinsmessageReceived, because store catch-up is on by default and a restart replays what the node missed while it was down, which consumers had no way to tell from live traffic; andmessageQueuedsurfaces a send held back because the epoch’s rate-limit budget is spent — not rejected, so the usual terminal events still follow logos-delivery-module#115, #121, logos-delivery-demo#31 - The demo shows RLN state rather than collecting it — a badge beside the connection badge, showing
Disabledrather than hiding itself, since that is what every shipped preset reports; the RLN panel reads its(registry, identifier)scope back fromrlnStateonce bring-up reachesReadylogos-delivery-demo#32 librlnis copied in prebuilt, so nix scanned nothing. Thelibiconvit names by absolute store path is zerokit’s dependency, not the module’s, and a tar is opaque to reference scanning — so the path was registered as a reference of nothing and the plugin failed todlopenwherever it was absent. It only ever arrived as a side effect of compiling the module; a warm cache is what exposed this class, and a cold one hid it logos-delivery-module#74, #112, #124, #119
Basecamp — links in, provenance out
basecamp://deep links. A URL scheme registered per platform, a single-instance guard, an inbox that holds a link arriving before the shell is ready, and a coordinator that turns it into the same intent an in-app request raises — 41 files, including the macOSInfo.plistand the.desktopentry logos-basecamp#392- “It would be installed from raw.githubusercontent.com” is the same string for every package published through GitHub, so it named nobody while reading like an answer. The publishing repository is shown instead — the name every other view spells it by, selectable, with a copy button and a page that opens — composed from the downloader’s
sourceOwner/sourceRepo, and used on the install-confirmation dependency rows too, where two forks of one catalog had rendered identically logos-basecamp#418 - Three more things the consent flow got wrong, all in the same PR: a chooser titled “Choose an app” over a list of one, where the broker deliberately sends a lone provider to be confirmed; approving by clicking a list row while refusing was a button — the safe action prominent, the intended one an affordance that does not look like one; and, with one provider installed, catalog packages that could also service the intent simply not shown, on the only screen where what a package provides is visible at all logos-basecamp#418
- Told what to type. A second instance now prints the
--new-instanceinvocation for the same directory rather than only refusing, and the A1–A17 UI suite dropped its dead branches and retry loops that could only pass instantly or spin logos-basecamp#417, #415, #419
Build, locks and process lifetime
- A module host died with the thread that loaded it.
logos_hostarmsPR_SET_PDEATHSIG(SIGKILL), and Linux ties that signal to the thread that spawned the child, not the process — while liblogos callsload()on whichever thread calledlogos_core_load_module, and its header describes off-thread loads as safe. Every POSIX child is now spawned from one dedicated process-lifetime thread. It was visible all along: once the thread-safety suite loaded real modules, every passing Linux run logged ~220Module process crashedlines and nothing asserted on them logos-container-subprocess#9, logos-liblogos#215, logos-test-modules#62, logos-module-loader-qt#16 - A
.lgxis a gzipped tar, so nix recorded no references for it — and#installis built from that archive, so it never saw the plugin’s store paths either. On a binary-cache hit the plugin’s libraries were simply missing. The derivation takes its payload’s runtime closure now, checked by aninstall-closurethat dlopens the installed plugin in a sandbox holding only that closure nix-bundle-lgx#7, logos-module-builder#254, nix-bundle-logos-module-install#9 - External libraries, three ways they were wrong. Staged copies kept the store’s read-only modes, so
fixCmakeFilescould not rewrite a library shipping a CMake package; test builds did not resolve bare flake inputs or copy nested headers the way the module build does; and the test rpath was joined with:— one CMake list entry, invisible on Linux where ELF joins with:anyway, and a dyld abort on macOS where each entry becomes its ownLC_RPATH. Plus a way for an entry to say where an input publishes a given system’s build, since zerokit ships its MinGW build underpackages.x86_64-linuxand we will not own every library a module wraps logos-plugin-qt#41, logos-module-builder#250, #251, #253, logos-test-framework#9, #8 - Checks that nothing built, and runners that swallowed failures. Seven plugin-qt checks had no CI step, so a guard now fails the job naming any check no step builds — assigning the eval result to a variable first, because
for c in $(nix eval …)turns a failed eval into a loop that runs zero times and passes.nix run .#testsexited 0 when a test binary failed, in libp2p as in storage logos-plugin-qt#43, logos-libp2p-module#110 - Windows.
WinSCard.dll— the PC/SC smart-card API, shipped in System32 since XP, reached through keycard support inwallet_ffi— joined the system-DLL list that the payload gate checks, which is what letlez_core’s Windows package build; storage-module gained anx86_64-windowstarget simply by taking itssystemsfrom the builder rather than a hard-coded four-element literal; and storage-ui dropped an unusedkrb5that is an evaluation-time hard failure for a mingw host nix-bundle-lgx#16, logos-storage-module#79, logos-storage-ui#86 - Storage config migration moved into the module, since the storage module is becoming a dependency of both logosctl and Basecamp and the migration path has to be one path; storage-ui dropped its own copy and calls
refreshConfig, and its plugin entry point is now generated rather than hand-written, the shape chat-ui already uses logos-storage-module#86, #82, #89, logos-storage-ui#92, #88 - Releases and the rest: the module catalog takes its runners and the Logos cache from repo settings and merged its base repo in as a real merge so later syncs are a plain
git merge;lgx sign --keyaccepts a path, since CI secret stores materialise keys under arbitrary names;dialWithAddrsreachesforceDialand spends one timeout on connect plus dial;getModuleStatscarries the pid that a per-module stat must be joined by; and the chat module publishes its API reference to GitHub Pages, with fork PRs building their own commit in the doc-tests logos-modules-release#61, #62, #60, #63, logos-package#41, logos-libp2p-module#109, logos-liblogos#217, logos-chat-module#68, #71, #72, logos-chat-ui#61, logos-logoscore-py#24, logos-execution-zone-module#57
Appendix: all merged PRs, by repo
logos-basecamp, logos-blockchain-ui, logos-capability-module, logos-chat-module, logos-chat-ui, logos-container-subprocess, logos-cpp-sdk, logos-delivery-demo, logos-delivery-module, logos-design-system, logos-evm-eth-rpc-module, logos-evm-fee-module, logos-evm-keystore-module, logos-evm-net-proxy, logos-evm-signer-ui, logos-evm-token-list-module, logos-evm-uniswap-module, logos-execution-zone-module, logos-liblogos, logos-libp2p-module, logos-lidl, logos-logoscore-cli, logos-logoscore-py, logos-module-builder, logos-module-loader-qt, logos-modules-release, logos-modules-release-tool, logos-modules-state-module, logos-package, logos-package-downloader, logos-package-downloader-module, logos-package-manager-ui, logos-plugin-qt, logos-protocol, logos-qt-sdk, logos-rust-sdk, logos-standalone-app, logos-storage-module, logos-storage-ui, logos-test-framework, logos-test-modules, logos-tutorial, logos-view-module-runtime, nix-bundle-lgx, nix-bundle-logos-module-install
logos-basecamp
- chore(deps): take catalog includes, and the pmui fixes riding with them (#428)
- chore(deps): take modules-state-module’s cycle cut — lock 3939 -> 2767 (#425)
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#424)
- chore: relock logos-protocol onto the subscription-continuity fixes (#422)
- Chore/rc3 (#419)
- fix: say where a package comes from, and stop hiding the alternatives (#418)
- feat: add explicit command when trying to start second instance on how to run new instance with same dir via —new-instance (#417)
- fix: Optimize A1–A17 UI tests (#415)
- feat: open Basecamp and its apps from a browser link (basecamp:// dee… (#392)
logos-blockchain-ui
- feat: unify accounts, channel deposit and transfer into one Wallet Tab (#72)
- Feat/complete dash board cards (#71)
- Feat/add blocks to dash board (#70)
- feat(units): show amounts in LGO, not raw base units (#69)
- feat: add stake notes info on dashboard (#68)
- feat(pow): mine and claim proof-of-work rewards from the UI (#67)
- Feat/clean ups for existing blocks (#66)
- feat(dashboard): rework node status, header and progress signals (#65)
logos-capability-module
logos-chat-module
- ci: build a fork PR’s own commit in the doc-tests (#72)
- docs: publish the v0.2.2 docs from a release branch (#71)
- docs: publish the module API reference to GitHub Pages (#68)
logos-chat-ui
logos-container-subprocess
logos-cpp-sdk
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#165)
- chore: relock logos-protocol onto the subscription-continuity fixes (#164)
- refactor: generate structural no-return methods (#163)
- Normalize and expose canonical module LIDL (#162)
logos-delivery-demo
- feat!: show RLN state instead of configuring RLN (#32)
- feat: bump delivery_module and show the message source (#31)
logos-delivery-module
- fix: make liblogos_rln_module an optional dependency (#126)
- chore: release v0.3.0-rc.1 (#124)
- build: bump logos-module-builder from 0.2.5 to 0.3.0 (#122)
- feat: bump logos-delivery and surface the queued send event (#121)
- Add enableValidation flag to rln preset (#120)
- docs: publish the v0.2.1 docs from a release branch (#119)
- feat!: RLN comes from the network preset, not from the client (#118)
- feat!: bump logos-delivery and surface the message source (#115)
- Remove duplicate lib files (#112)
- flake: bundle what librln loads (#74)
logos-design-system
- fix: copy button on caption in StatCard (#61)
- fix: caption size in Stat Card (#60)
- feat: add states for LogosStatCard and expose property so that infoBu… (#58)
- feat(statcard): add valueColor, so a tint stops implying a verdict (#57)
- feat: add LogosStatCard, LogosStageLane and LogosInfoButton (#56)
logos-evm-eth-rpc-module
- docs: name today’s callers in the specs (#18)
- fix: offer each default chain once per device (#17)
- fix: keep eth_feeHistory’s block count hex on the verified leg (#16)
- chore(metadata): version 0.1.0, verified_proxy_module at ~0.1.0 (#15)
- feat: add reusable EVM chain registry (#14)
logos-evm-fee-module
- chore: relock onto the modules’ current mains (#10)
- fix: honour a lone fee field (#9)
- fix: a fee read that fails is an error, never a zero tip (#8)
- chore(metadata): version 0.1.0, dependencies at ~0.1.0 (#7)
- feat: estimate a bundle as the chain will find it, and answer ceilings in the native unit (#6)
logos-evm-keystore-module
- docs: name today’s callers in the specs (#22)
- feat: show the fee a transaction signs (#21)
- docs: say what the approval sweep actually does (#20)
- fix: a displaced approval stays approvable (#19)
- test: keep the on-disk state tables inside their own temp dirs (#18)
- chore(metadata): version 0.1.0 (#17)
- feat: expose account wallet provenance (#16)
- feat: an EIP-712 typed-data approval leg (#15)
logos-evm-net-proxy
logos-evm-signer-ui
- chore: relock onto the modules’ current mains (#20)
- chore: relock logos-tx-decoder onto its swap reading (#19)
- docs: name today’s callers in the specs (#18)
- chore(metadata): version 0.1.0, dependencies at ~0.1.0 (#17)
- chore(deps): bump tx decoder (#16)
logos-evm-token-list-module
- fix: answer reads while a token list downloads (#11)
- docs: init_defaults needs no config_status gate (#10)
- chore(metadata): version 0.1.0 (#9)
- feat: own persisted offered token sets (#8)
logos-evm-uniswap-module
- chore: relock onto the modules’ current mains (#14)
- docs: name today’s callers in the specs (#13)
- feat: relay eth_rpc’s refusals whole (#12)
- chore(metadata): version 0.1.0, dependencies at ~0.1.0 (#11)
- feat: a complete quoter and encoder for any pair, on SwapRouter02 (#10)
logos-execution-zone-module
logos-liblogos
- chore(deps): take modules-state-module’s cycle cut — lock 880 -> 294 (#221)
- chore(deps): take the relocked bundled modules — unconfigured-replica UAF (#220)
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#218)
- flake: bump process-stats to 6e0aade7 (emit pid in getModuleStats) (#217)
- chore: relock logos-protocol onto the subscription-continuity fixes (#216)
- fix: hosts outlive the thread that loaded them (relock default-container) (#215)
logos-libp2p-module
- fix(flake): fail
nix run .#testswhen a test binary fails (#110) - feat: add dialWithAddrs, bump nim-libp2p and the flake inputs (#109)
logos-lidl
- feat(cli): a lidl command-line tool (json, check, fmt) (#14)
- refactor: model no-return methods structurally (#13)
- Add canonical lidl() module identity method (#12)
logos-logoscore-cli
- chore(deps): take the downloader module that carries catalog includes (#140)
- feat(catalog): show the catalogs a catalog draws from (#139)
- chore(deps): take modules-state-module’s cycle cut — lock 16886 -> 15714 (#137)
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#136)
- chore: relock logos-protocol onto the subscription-continuity fixes (#135)
logos-logoscore-py
logos-module-builder
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#256)
- chore: relock logos-protocol onto the subscription-continuity fixes (#255)
- fix(deps): relock nix-bundle-lgx so lgx and install keep the plugin’s runtime closure (#254)
- feat(extlib): say where an input publishes each system’s build (#253)
- chore(deps): relock logos-plugin-qt and logos-plugin-core onto e46678a (#252)
- fix(tests): resolve and stage external libraries as the module build does (#251)
- fix(tests): pass external lib dirs to CMake as a list (#250)
- fix: canonicalize legacy no-return contracts (#249)
- feat: configure bounded multi-dispatch workers (#248)
- Bundle canonical LIDL contracts with modules (#247)
logos-module-loader-qt
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#18)
- chore: relock logos-protocol onto the subscription-continuity fixes (#17)
- docs(host): PR_SET_PDEATHSIG is scoped to the spawning thread, not the daemon (#16)
logos-modules-release
- bump json-rpc-bridge (#63)
- chore: merge logos-modules-release-base main (#62)
- release: take runners and the Logos cache from repo settings (#61)
- chore: bump LEZ Core (#60)
logos-modules-release-tool
logos-modules-state-module
- fix(flake): cut the builder’s logos-standalone-app input — lock 690 -> 104 (#5)
- chore(deps): relock onto logos-module-builder de169fd — unconfigured-replica UAF (#4)
logos-package
- feat(extract): extract root assets without unpacking a variant (#42)
- sign: accept a key file path in —key (#41)
- Support platform-independent root assets in LGX packages (#40)
logos-package-downloader
logos-package-downloader-module
logos-package-manager-ui
- feat(details): say which catalog actually published a package (#83)
- fix(details): a Local row showed no dependencies at all (#82)
- fix(packages): tooltip the selected version when the cell elides it (#80)
logos-plugin-qt
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#45)
- chore: relock logos-protocol onto the subscription-continuity fixes (#44)
- ci: build every check, and fail when one has no step (#43)
- fix(glue): refuse lidl() with arguments as invalid_args (#42)
- fix(buildPlugin): leave staged external libraries writable (#41)
- refactor: consume structural no-return methods (#40)
- feat: bound multi-dispatch worker concurrency (#39)
- Generate canonical LIDL host support (#38)
logos-protocol
- fix(qt_remote): never free a replica that has not reached Valid (#95)
- fix(plain): a call on the io thread never waits on the redial (#94)
- fix(plain): bound the first connect with the redial’s deadline (#93)
- fix(plain): a provider that restarts over TCP is reported and re-armed (#92)
- fix(subscriptions): a sub-second provider swap is a restart, not continuity (#91)
logos-qt-sdk
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#59)
- chore: relock logos-protocol onto the subscription-continuity fixes (#58)
- refactor: consume structural no-return methods (#57)
- Generate lidl() Qt consumer bindings (#56)
logos-rust-sdk
- refactor: generate structural no-return methods (#62)
- Expose canonical LIDL from Rust providers (#61)
logos-standalone-app
- chore(deps): take liblogos 71dabe0 — modules-state cycle cut, lock 898 -> 312 (#57)
- chore(deps): take liblogos 8008b8e — its bundled modules carry the UAF fix (#55)
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#54)
- chore: relock logos-protocol onto the subscription-continuity fixes (#53)
logos-storage-module
- chore: update logos storage nim (#89)
- feat: refresh config (#86)
- feat: expose network configuration (#82)
- feat(windows): expose an x86_64-windows target (#79)
logos-storage-ui
- feat: update Storage Module to refresh config (#92)
- feat: migrate storage_ui to a generated universal view plugin (#88)
- fix(windows): drop unused krb5, and make the icon 256x256 (#86)
logos-test-framework
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#11)
- chore: relock logos-protocol onto the subscription-continuity fixes (#10)
- feat(LogosTest): EXTERNAL_LIBS links real external libraries (#9)
- fix: make the repo’s own checks build (relock, sandbox cmakeDir, CI) (#8)
logos-test-modules
- chore(deps): relock onto logos-protocol dcf4f05 — subscription continuity (#65)
- conformance: lidl(“junk”) is refused like any zero-parameter call (relock onto module-builder 8007924) (#64)
- chore(deps): relock onto module-builder 87e2f97 — canonical lidl() (#63)
- fix(thread-safety): hosts outlive the threads that loaded them (relock logos-liblogos) (#62)
logos-tutorial
logos-view-module-runtime
- chore(deps): relock onto logos-protocol 8bbc027 — unconfigured-replica UAF (#35)
- chore: relock logos-protocol onto the subscription-continuity fixes (#34)
nix-bundle-lgx
- fix: treat WinSCard.dll as a Windows system DLL (#16)
- Bundle platform-independent LGX assets (#15)
- fix: give the .lgx derivation its payload’s runtime closure (#7)