Skip to content

V1.153 P2 — nexus-runtime headless bin + Windows x64 export (DF-73) - #201

Merged
btspoony merged 27 commits into
iteration/v1.153from
plan/v1.153-p2-nexus-runtime-headless-bin-windows-x64
Aug 7, 2026
Merged

btspoony merged 27 commits into
iteration/v1.153from
plan/v1.153-p2-nexus-runtime-headless-bin-windows-x64

Conversation

@btspoony

@btspoony btspoony commented Aug 6, 2026

Copy link
Copy Markdown
Member

Plan: 2026-08-06-v1.153-p2-nexus-runtime-headless-bin-windows-x64

  • T1 (merged into this branch): nexus-runtime bin target with headless Connect-only boot (web-embed gate OFF for the slim artifact), boot smoke test.
  • T2 (in progress): runtime-build.yml — native 3-platform build (windows-x64 / macos-arm64 / linux-x64), zip + sha256 packaging, --version smoke.

Draft opened as the CI vehicle for T2 iteration (workflow file does not exist on the default branch yet; temporary pull_request trigger removed in the final T2 commit). PM handles merge/delivery.

…nect)

V1.153 P0 wave 0: workspace spoke deps move 0.8.2 → 0.9.1 lockstep across
Rust (spoke-schemas/spoke-operations/spoke-connect =0.9.1) and npm
(@42ch/spoke-schemas/@42ch/spoke-operations 0.9.1). libp2p =0.56.0 pin
unchanged (spoke-connect 0.9.1 still requires =0.56.0; feature-on graph
shares ONE libp2p build, default build stays libp2p-free, mdns off).
check-wire-drift.sh SPOKE_PIN → 0.9.1; pin-citing comments updated.
codegen + validate-schemas + wire-drift + schema-drift gates green;
generated output unchanged.
…ns 0.9.1 async surface

spoke-operations 0.9.1 converted the 8 adapter port traits to
#[async_trait] async fn and orchestrate_* to native async fn (T1
finding; pure sync->async, no compat shim). Signature-level
adaptation only — no behavior/logic changes:

- 8 production port impls (knowledge_entry/relation/scope_query/
  finding/rule_query/host_manifest/computable/fork) become
  #[async_trait] async fn awaiting SQLite I/O directly; the
  Handle::block_on + block_in_place sync bridge (mod.rs block_on
  helper, handle field, runtime-flavor debug_assert) is removed
  as dead machinery.
- Inherent helpers commit_compute_settlement, list_hop_edges_for_world,
  list_timeline_events_ordered become async fn.
- Mock port impls (example baseline_adapter, orchestration_adoption
  BaselineOnlyPorts) adopt #[async_trait] async fn; mock storage
  RefCell -> Mutex so the Send futures type-check.
- ~90 call sites await: daemon-runtime pack_import (persist fns made
  async), check/world_kb/inspector handlers (with_bound_tx sites
  await outside the sync passthrough), CLI context.rs hop loader,
  and adapter tests/examples ([test] -> [tokio::test] where needed).
- async-trait added as workspace dep of nexus-spoke-adapter.
- Stale block_in_place bridge prose in docs/comments updated.

Gates: cargo check --workspace --all-features PASS; cargo test
-p nexus-spoke-adapter -p nexus-daemon-runtime --all-features PASS
(1228 tests, 0 failures); baseline_adapter example runs with
identical outcomes; libp2p graph unchanged (1x v0.56.0 under
connect-host, libp2p-free default, mdns off).
…ken issuance

0.9.1 issue_capability_token gained a mandatory now (Unix seconds)
parameter and fail-fast issuance guards (exp must clear the clock-skew
window). Re-baseline the N-C0 interop suite fixtures on the new
signature, mirroring the upstream 0.9.1 reference test shape: token
provider/proof helpers issue at now with a one-hour lifetime; the
expired-token fixture backdates the issuance time so the mint-time
guards pass while the verifier's clock rejects the proof.

Handshake, op_unsupported refusal, and manifest honesty assertions are
unchanged.
- spec §1.1/§5.2/§10.1: lockstep pins 0.8.2 → 0.9.1 (all 5 spoke pins);
  add durable async port-surface note (§7.3) + V1.153 historical entry;
  bump spec revision to v0.13
- check-wire-drift.sh: Gate 1 now enforces all 5 in-repo spoke pins
  (spoke-connect Cargo pin was previously unenforced)
- Cargo.toml: V1.153 comment no longer implies operations-surface
  parity — records the sync→async conversion (T2)
- mca_read.rs: drop stale runtime-Handle/panic prose from
  SpokeBackedKbStore::new (constructor works anywhere post-T2)
- world_kb.rs: promote_adopt doc sync-bridge → native-async wording
- AGENTS.md: native-async adapter description + stale =0.8.2 pins
- adapter/mod.rs: NexusAdapter::new → const fn (clippy -D warnings
  missing_const_for_fn, surfaced by the T4 full-gate sweep)
Plan 2026-08-06-v1.153-p0-spoke-091-pin-and-connect-v2-adaptation: 4 SDD tasks (T1 pin bump + codegen/drift; T2 spoke-operations
sync→async signature adaptation; T3 N-C0 interop/honesty re-baseline; T4
full-gate sweep + spec/gate/doc sync). Plan QC tri Approve (0 Critical /
0 Warning). pm-acceptance (AC-1 green).
…cope gate

T1 of the P1 inbound-write-ops plan. allowlist.json peer_ids entries are
now PeerEntry = bare peer id (N-C0) | { peer_id, world_scope?: [world-uuid],
op_scope?: [ops] } with deny_unknown_fields retained on both file and
scoped-object forms (P1 spec § World scoping — schema locked).

load() now returns PeerScope (peer -> allowed world ids + allowed ops):
peer_ids() feeds ConnectConfig.peer_allowlist (handshake), and
allows_world/allows_op feed the T2 dispatch gate. Fail-closed semantics:
absent/empty scope denies world writes; --allow-peer overlay carries no
scope and never strips a hand-authored file scope; missing file stays an
empty allowlist.

TDD: 8 new scoping tests (listed-world allow, cross-world deny, absent
world/op scope deny, unknown-field and invalid-peer-id config errors, CLI
overlay gap-fill, unknown-peer deny) + 6 existing tests adapted to the
PeerScope return type.
…ate via workspace adapter

V1.153 P1 Task 2 (N-C1 core write path): architect-locked invoke.rs owns the
InvokeHandler closure; the connect start boot now opens the active-workspace
SQLite pool (WAL; daemon resolution rules), constructs one per-process
NexusAdapter, and wires upsert/promote/relate through the spoke orchestrators
with the locked SpokeRejectCode->ErrorEnvelope mapping. Fail-closed gates:
served-op set, payload-resolved calling peer (extensions.nexus.peer_id),
PeerScope op_scope + world_scope before any dispatch. All other ops stay
op_unsupported with zero side effects. Integration test: write round-trips
(upsert CAS accept + stored_revision_stale + revision_conflict, promote,
relate), wrong-world/absent-scope/unknown-op denial with no DB mutation.
…n N-C1 dispatch

L2 review findings (task-2 fix loop):
- Critical: orchestrators' stored lookups and CAS updates are
  world-agnostic (id + revision only), so a payload claiming world A could
  rewrite a row stored in world B by replaying the revision disclosed by
  OCC rejects. New stored-world gate (before the orchestrator CAS) verifies
  every targeted existing row's stored world_id against the payload-claimed
  world_id for update/promote/relate; mismatch denies with zero side
  effects.
- Important: payload_world_ids filter-mapped world-less entries out of the
  gate's world set, letting a mixed multi-entry upsert pass and fail later
  as a partial write (internal_error). The gate now requires EVERY
  entry/relation to carry extensions.nexus.world_id; one missing denies the
  whole payload.

Regression tests (TDD red->green): cross-world update/promote/relate denied
with zero mutation; mixed payload denied with zero entries persisted.
…ered-shape lock

The manifest now advertises the delivered N-C1 slice:
extensions.nexus = { connect_host_slice: "n-c1", served_ops:
["upsert", "promote", "relate"], daemon_http_coexists: true }.

Honesty is machine-checked both directions: the crate-level
n_c1_manifest_is_honest test (renamed from n_c0_manifest_is_honest, N-C0
baseline kept) asserts the advertised set is exactly LOCAL_SERVED_OPS and
that every advertised op maps to a production orchestrator (typecheck-only
closure proof); the connect-host interop test
n_c1_manifest_served_ops_match_dispatch_both_directions compares the
wire manifest a peer reads off the signed hello against the dispatch's
SERVED_OPS table (a: advertised ⊆ served, b: served ⊆ advertised).

Interop evidence (Step 2): n_c1_peer_upserts_promotes_relates_with_world_scoping
already runs the full upsert → promote → relate round-trip against a real
SpokeConnectNode host process (full N-C1 CLI boot path, real TCP loopback,
signed-hello handshake, invoke wire, real SQLite workspace) — verified,
not duplicated.

Spec .mstar/specs/spoke-adapter-architecture.md: §10.3 N-C1 field
extension, §10.4 N-C1 refusal-contract extension, §10.6 N-C1 row updated
to the delivered shape (ops served, OCC, fail-closed world scoping +
stored-world gate, WAL coexistence, payload-carried peer_id as E2
residual).
Plan 2026-08-06-v1.153-p1-connect-inbound-write-ops-n-c1: 3 SDD tasks (T1 allowlist world-scope + fail-closed gate;
T2 invoke dispatch upsert/promote/relate via workspace adapter + cross-world/
mixed-payload fix; T3 manifest honesty both-directions + spec §10.6 + SERVED_OPS
load-bearing fix) + plan QC fix wave (relate endpoint worlds + multi-write-peer
warning). QC tri Approve with residuals (3 E2-defers: R1 peer_id spoofing,
R2 block_in_place stall, R3 cross-process TOCTOU). pm-acceptance (AC-2 green).
…oot smoke (V1.153 P2 T1)

- [[bin]] nexus-runtime (required-features connect-host) booting the shared
  connect start N-C1 assembly (build_host_config) — run_daemon never called;
  stdout-only readiness, no HTTP health endpoint, --home/NEXUS42_HOME override
- web-embed feature on nexus-daemon-runtime (default ON; gated: rust-embed dep,
  static_assets mod, api SPA fallback import+route); nexus42 forwards it
  (default ON) and declares the dep with default-features=false, so the slim
  artifact (--no-default-features --features connect-host) excludes the SPA
  while the default nexus42 bin is unchanged
- tests/nexus_runtime_smoke.rs spawns the real binary against a temp
  NEXUS42_HOME: stdout readiness, Connect handshake via the runtime_smoke_probe
  example (N-C1 manifest served_ops), no HTTP/SPA listener (per-PID lsof),
  --version; probe example is connect-host-gated so the default graph stays
  libp2p-free
…(V1.153 P2 T2)

Builds the headless nexus-runtime bin with --no-default-features
--features connect-host (web-embed OFF) natively on windows-latest
(x86_64-pc-windows-msvc), macos-latest (aarch64-apple-darwin), and
ubuntu-latest (x86_64-unknown-linux-gnu); packages nexus-runtime-<os>-<arch>.zip
+ .sha256, uploads them, and smoke-tests --version on each runner.

Temporary push trigger scoped to the plan branch for iteration
(workflow_dispatch requires the workflow on the default branch);
removed in the final T2 commit. Delivered trigger set stays
workflow_dispatch + tag runtime-v*.
A workflow file added by a push does not run for the creating push; this
empty commit makes GitHub evaluate the temp-push-triggered workflow (T2
iteration scaffolding; removed in the final T2 commit).
A workflow file that exists only on a non-default branch is not evaluated
for push events (GitHub's workflow registry is built from the default
branch; verified: no check suite was created for the plan-branch pushes).
The documented iteration vehicle for an unregistered workflow is a
pull_request trigger + PR against the spec integration branch. Removed in
the final T2 commit; delivered trigger set unchanged (workflow_dispatch +
tag runtime-v*).
…w files on this repo? (T2 diagnostic, removed)
btspoony pushed a commit that referenced this pull request Aug 6, 2026
…I iteration (V1.153)

GitHub Actions evaluates workflow files only on the default branch for
push/pull_request/workflow_dispatch events. The plan-branch copy does not
register. This commit places the workflow on main so PR #201 (plan branch →
iteration/v1.153) triggers the matrix. The temporary pull_request trigger
(scoped to iteration/v1.153) is removed in the final T2 commit on the plan
branch; the delivered trigger set is workflow_dispatch + tag runtime-v* only.
…continuation) + restore temp push trigger

Windows runners default to pwsh, which rejects the multi-line
backslash continuation — 'Missing expression after unary operator'
parse error. One line works on all three shells. Both temp triggers
(push on plan branch + pull_request on iteration/v1.153) restored for
iteration; removed in the final T2 commit.
…untime builds on windows-msvc (V1.153 P2 T2)

Root cause (surfaced by the new Windows CI leg): nexus-local-db's
file_lock module is flock-based and documented 'Unix-only (the entire
module is #[cfg(unix)])', but no cfg gate existed — pub mod file_lock;
compiled unconditionally, breaking every Windows build of the runtime
graph (nix::fcntl::flock + AsRawFd on windows-msvc: E0432/E0433/E0599).

Fix follows the repo's existing precedent (works/mod.rs status JSON and
script_section_status.rs already gate file_lock usage):
- crates/nexus-local-db/src/lib.rs: #[cfg(unix)] pub mod file_lock;
- nexus-local-db + nexus-daemon-runtime + nexus42 lock integration
  tests: #![cfg(unix)] (or #[cfg(unix)] per-test)
- Consumers proceed unlocked on non-unix (WAL-governed shared-DB writes
  per P2 spec § Coexistence; the headless runtime never takes the
  per-Work advisory lock):
  - creator/run.rs, creator/works/cron.rs, creator/world/kb/mod.rs:
    cfg-split the RAII guard binding
  - creator/kb/rescan.rs acquire_work_lock + orchestration
    cron_supervisor maybe_acquire_cron_file_lock: cfg(unix) impl +
    cfg(not(unix)) no-op stub with the same call shape

Unix behavior unchanged: file_lock integration tests 3/3, cron lock
integration 3/3, kb_rescan 11/11 incl. the 3 AC5 lock tests,
works_status_lock_holder 2/2; canonical clippy -D warnings and nightly
fmt --check pass.
…l code for windows-msvc (V1.153 P2 T2)

Second batch of Windows compile blockers surfaced by the CI leg
(nexus-local-db built; these were next in the graph):
- nexus-local-db: 'pub mod cas;' was wrongly #[cfg(unix)]-gated although
  cas.rs is pure SQL (OCC helpers) — kb_relationships imports it
  unconditionally (E0432 on Windows). Removed the gate.
- nexus-daemon-runtime api/handlers/strategy.rs: StrategyLockGuard flock
  was un-gated (std::os::fd::AsRawFd + nix::fcntl::flock). Gated the
  guard + acquire fn on unix; not(unix) no-op unit guard, same call
  shape (callers unchanged: let _guard = acquire_strategy_lock(...)?).
- nexus-daemon-runtime boot.rs run_daemon: tokio::signal::unix SIGTERM/
  SIGINT spawn was un-gated. Unix keeps both; not(unix) uses the
  cross-platform tokio::signal::ctrl_c() with the same graceful
  ShutdownRequested dispatch.

Canonical clippy -D warnings + nightly fmt --check pass on unix; unix
behavior unchanged (gates are additive).
…(V1.153 P2 T2)

Windows compile blocker surfaced by the CI leg: the #[cfg(windows)]
branch of AgentProcess::shutdown moved self.agent_path (PathBuf,
non-Copy) into two map_err closures -> E0382 use of moved value.
Latent since the branch was never compiled on macOS/Linux CI.

Unix branch is unaffected (its first agent_path use sits on a return
path, so the borrow checker allows the later closure capture); the
windows branch clones per closure on the error path only.
…V1.153 P2 T2)

The strategy.rs flock gate added in the previous commit covered the
guard + acquire fn but left the top-level 'use std::os::fd::AsRawFd;'
ungated — std::os::fd does not exist on windows-msvc (E0432).
…nix-gated by accident (V1.153 P2 T2)

dialoguer/tempfile/regex/base64/cron/chrono-tz were declared after
nix under [target.'cfg(unix)'.dependencies] with no [dependencies]
header, so the Windows build of the nexus42 lib failed with 15
'cannot find crate' errors (E0433) in lib code that uses them on all
platforms (works/cron.rs cron::Schedule validation, auth/user_auth.rs
base64, creator/memory.rs tempfile, rules_runtime.rs dialoguer).

Never caught before: no Windows CI existed; on unix the target-gated
deps resolve identically. Unix dep graph and Cargo.lock unchanged.
… of the unix target section (V1.153 P2 T2)

They were declared after nix under [target.'cfg(unix)'.dependencies]
without a [dependencies] header (TOML tables extend until the next
header), making every Windows build of the nexus42 lib fail with
E0433 'cannot find crate' in lib code used on all platforms. Moved
into the existing [dependencies] section; unix dep graph unchanged.
…orkflow_dispatch + tag runtime-v* (V1.153 P2 T2 final)

Temporary push (plan branch) and pull_request (iteration/v1.153)
triggers removed per the locked Clarify #3 trigger set; the workflow is
verified green on all three matrix legs (windows-x64, macos-arm64,
linux-x64) with artifacts + checksums uploaded. workflow_dispatch
becomes available once merged to the default branch (E2+ release
polish).
@btspoony
btspoony merged commit a415ef2 into iteration/v1.153 Aug 7, 2026
@btspoony
btspoony deleted the plan/v1.153-p2-nexus-runtime-headless-bin-windows-x64 branch August 7, 2026 06:58
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.

2 participants